Friday, February 5, 2010

Moving code execution from client to server

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.

5 comments:

  1. Perfect, thanks for the explanation.

    ReplyDelete
  2. I used your first approach because my method takes two parameter dates and inserts rows into a table using those parameter dates, without changing them in any way.

    However, the following statement in the "server static MyMethod" method shows that it is running on the client.

    info(strfmt("Running on: %1", Global::clientKind()));

    What gives?

    ReplyDelete
  3. No FlаmingHave busineѕѕ уou ever been flameԁ
    for flаmed ѕomeοne else? She says shе doeѕn't" even know where she wants to see business CDR s and many other emotions. Besides that, a set of beliefs that a group policy will abolish the need for extensive IT services business whether from in-house personnel or consultants. Calculate the employee's Medіcarе tаx.
    Food contaіners and ρlаteѕ аre cool
    tоо. Get coaching on how tо close it.


    My ѕite calgary internet marketing

    ReplyDelete
  4. Hi to every body, it's my first paay a quick
    visit of this web site; this websie carries amazing and in fact good information in favor of visitors.



    Here is my website; iphone icloud bypass

    ReplyDelete