calling asynchronous appserver procedure from class

Posted by kristjan.karp on 12-Feb-2019 08:58

Hi,

i try to create functionality for calling multiple requests from different appservers in parallel ( asynchronous ) and merge the results together later.

It works ok with procedure

    run asyncAppserver/asProc2.p persistent set ttProcessExec.procHandle
                                on server ttProcessExec.asHandle  .
    run sleepingTime asynchronous set ttProcessExec.runHandle
                     event-procedure "asyncRunResult" in this-procedure
                     in ttProcessExec.procHandle
                         ( ttProcessExec.procId, output returnMsg, output totTimeUsed ).

NB: ttProcessExec is temp-table to hold all the different handles and info for the appsetrver calls

but it wont work when i try to do same with OO ( inside class ), there 'this-procedure' cannot be used but unsing 'self' will generate an error 'invalid event-procedure context used with asynchronous request (8977)'.

What should i do to get it work with OO also?

the call:

            run asyncAppserver/asProc2.p persistent set ttProcessExec.procHandle
                                         on server ttProcessExec.asHandle.
            run sleepingTime asynchronous set ttProcessExec.runHandle
                             event-procedure "asyncRunResult" in self
                             in ttProcessExec.procHandle
                                 ( ttProcessExec.procId, output returnMsg, output totTimeUsed ).

event procedure ( in same class):

    method public void asyncRunResult(
        asyncReturnMsg as character,
        timeUsed as integer ):
        
        totTimeUsed = totTimeUsed + timeUsed.
        run writeLog ( "async result: " + asyncReturnMsg + " - usedTime:" + string( timeUsed ) + " totTime: " + string( totTimeUsed ) ).
    end method.

test procedure:

using asyncAppserver.clCls.
def var asObj as clCls no-undo.
asObj = new clCls().
asObj:executeProcs().
delete object asObj no-error.

br,

kristjan karp

Posted by frank.meulblok on 12-Feb-2019 09:22

You'll need to set up a persistent procedure that acts as a helper to handle the events. The event procedures in that helper can call back into the class for the actual logic. (Keeps the real functionality in one place, makes it easier to remove the helper in case Progress finally decides to lift these limitations after ... 13 years I think ?)

Basic outline is described here: knowledgebase.progress.com/.../P120881

This KB article: knowledgebase.progress.com/.../P168296 has a more complete example for  a similar scenario for COM objects,

Only real difference for async appserver calls is that instead of using the " RUN enableevents IN hhelperproc (INPUT  chExcelApplication).", you'd specify the persistent procedure handle as your event-procedure in the RUN ... ASYNC statement to make sure the helper gets properly registered as the event handler.

All Replies

Posted by frank.meulblok on 12-Feb-2019 09:22

You'll need to set up a persistent procedure that acts as a helper to handle the events. The event procedures in that helper can call back into the class for the actual logic. (Keeps the real functionality in one place, makes it easier to remove the helper in case Progress finally decides to lift these limitations after ... 13 years I think ?)

Basic outline is described here: knowledgebase.progress.com/.../P120881

This KB article: knowledgebase.progress.com/.../P168296 has a more complete example for  a similar scenario for COM objects,

Only real difference for async appserver calls is that instead of using the " RUN enableevents IN hhelperproc (INPUT  chExcelApplication).", you'd specify the persistent procedure handle as your event-procedure in the RUN ... ASYNC statement to make sure the helper gets properly registered as the event handler.

Posted by kristjan.karp on 12-Feb-2019 10:24

Thx for the answer,

i try this possibility out,

but in the quick view seems like for this task it might be more reasonable to do it in 'progress way' aka use procedure.

Posted by jquerijero on 12-Feb-2019 15:28

Just one note, you will need to track if the callback already happened before killing the persistent procedure, which is very like being cleaned up when the class is freed up. You will get a run-time error when the async comes back and can't find the callback handler.

Posted by frank.meulblok on 12-Feb-2019 16:36

You could avoid having the class instance getting freed/deleted before the async requests have completed.

You could also avoid that by having the persistent procedure delete itself at the end of the event procedure, instead of wiring that into the class' destructor.

Of course if you go that route, you want to start off the event procedure with makeing sure the class instance is still around to invoke the method, and either raise an error or discard the response if it isn't.

This thread is closed