This post replies to this question from the comments.
There are two ways to move the execution of some code from client to server. Choosing one way or another depends on the purpose and complexity of the code to be moved.
Simple way - static server method.
This one is applicable when the code to be executed on server does not affect owning object's state. For example, if MyClass class has the following method run() :
public void run()
{
while select forupdate table1
{
table1.Field1 = instanceMember1;
table1.Field2 = instanceMember2;
table1.update();
}
}
The code depends on the object state – instanceMember1 and instanceMember2, but does not modify it. In this case code can be rewritten in the following way.
public void run()
{
MyClass::runOnServer(instanceMember1, instanceMember2);
}
private static server void runOnServer(SomeType1 _arg1, SomeType2 _arg2)
{
while select forupdate table1
{
table1.Field1 = _arg1;
table1.Field2 = _arg2;
table1.update();
}
}
Complex way – serialization.
This one should be used when the job to be moved on server modifies object state. In this case the client-side object should be serialized to some data structure -package (for example, container in the standard pack\unpack serialization approach). Then a new instance of the same class as client-side object should be created on the server and de-serialized from the package – so we get exactly the same objects on client and server. After that the job should be executed on the server-side object. Then server-side object is serialized to a package and client-side object (the initial one) is de-serialized from the package. So, the client-side and server-side objects are the same again with the state as it should be after job execution.
Example:
public void run()
{
while select forupdate table1
{
table1.Field1 = instanceMember1;
table1.Field2 = instanceMember2;
instanceMember1 += 1;
instanceMember2 += 2;
table1.update();
}
}
Will be rewritten as:
public void run()
{
MyClass myClassOnServer;
if (!isRunningOnServer())
{
myClassOnServer = MyClass::constructOnServer();
myClassOnServer.unpack(this.pack());
myClassOnServer.run();
this.unpack(myClassOnServer.pack());
}
else
{
while select forupdate table1
{
table1.Field1 = instanceMember1;
table1.Field2 = instanceMember2;
instanceMember1 += 1;
instanceMember2 += 2;
table1.update();
}
}
}
public static server MyClass constructOnServer()
{
return new MyClass();
}
public container pack()
{
return [instanceMember1, instanceMember2];
}
public void unpack(container _packedClass)
{
instanceMember1 = conpeek(_packedClass, 1);
instanceMember2 = conpeek(_packedClass, 2);
}
Note, that in this example there will be 4 client-server RPC calls: call of constructOnServer(), unpack(), run() and pack() methods. This number can be reduced to only one call by wrapping all the calls by server static method but in the example it wasn’t done for better readability.
Moving code execution from client to server
This was originally posted here.
*This post is locked for comments