[SOLVED] run operation asynchronous

Author: m.doorne@amyyon.nl (Doomic)

We have a service component that contains an operation that may take a minute to complete. The other code is not depending on it. so we like to run this async. The operation is activated from another service component that has been activated by an DSP component. (userver proces). Whatever i try, i can't get it working. What i have tried:

activate/async "service".asyncOperation("data")

But this gives a $status of -161 "Illegal mixture of synchronous and asynchronous communication modes" therefor i moved the asycOperation to a new service component (to be sure there doesn't exists an instance of this component)

activate/async "asyncService".asyncOperation("data")

still got a -161

newinstance/async "asyncService", vAsyncService activate/async vAsyncService.asyncOperation("data")

no error when newinstance is called, but still -161 on activate.   next i tried to use "Asynchronous Messaging". But found later that this is not posible in an userver proces. If the receiving component is running in the same userver process, the message is converted to a synchronous send message But i leads me to the UTIMER component.

activate "UTIMER".start("00.00.02") activate "UTIMER".setMessage("asyncService", "MessageId001", "data") activate "UTIMER".setRepeat(1)

All activates gives $status 0, but the Asynchronous Interupt trigger in the asyncService is never called. Also tried to place the activates in another order, but this found this order in some documentation, and reordering didn't let it work. Placed a sleep of 400 at the end to make sure the timer sends the message before the webrequest is finished.. not results..   now i am lost. Don't know where to look. Any suggestions? or explanaition why the activate/async is not working?

6 Comments

  1. Doomic said I don't understand what i did wrong last time... but it is working now! Still don't like the flow where you have to setup and configure a new userver process... but it is something i can live with. Thank you  

    Thanks for the info. I'm glad to hear that you got this working now. Kind regards, Daniel


    Author: diseli (daniel.iseli@uniface.com)
  2. Doomic said Thank you for the reply, I have add a new server to the urouter.asn. Redirect the asyncService to the urouter with the other server name. Took me a while to get this running.. but at the end.. i got my -161 status back!
    ERROR=-161 MNEM= DESCRIPTION=Illegal mixture of sync and async COMPONENT=TESTSERVICE PROCNAME=TESTOPERATION TRIGGER=OPER LINE=534 ADDITIONAL= INSTANCENAME=ASYNCSERVICE(EXTERN:0X00000007) OPERATIONNAME=ASYNCOPERTATION

    In case you are still getting the -161 error then the service is still executed locally (I'm afraid). In case you start the process with $ioprint=1024 (shows the network messages) then you can see that the activate is contacting the URouter. Here's an excerpt from a log file I've created (with Proc tracing):

    [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 1; [0]; activate/async "ASYNCSVC1"."OPER1ASYNC"( ) To Router:chn=1041;len=123: ACTREQ; typ=A;av=I;op=i;mod=0;iop=1088;ign=0; hop=0;dbg=0;pid=16620;tid=1868;qid=0;ins=0; From Router:chn=1041;len=65: ANSWER; typ=Z;av=S;op=Z;ret=0,0; hop=0;dbg=0;pid=16620;tid=1868;qid=0;ins=0; To Router:chn=1041;len=146: ACTREQ; typ=A;av=O;op=a;mod=2;iop=1088;ign=0; hop=0;dbg=0;pid=16620;tid=1868;qid=0;ins=0; [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 2; [0]; if ($procerror < 0) [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 5; [0]; else [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 6; [0]; webmessage/info "activate/async was successful!" [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 7; [0]; endif And here's the output from the UServer log file where the service is executed asynchronously:

    From Router:chn=725;len=146: ACTREQ; typ=A;av=O;op=a;mod=2;iop=1088;ign=0; hop=0;dbg=0;pid=16620;tid=1868;qid=0;ins=0; [C=ASYNCSVC1][I=_I00000001][S=0] (_OPER); OPER1ASYNC; 1; [0]; putmess "[OPER1ASYNC] - Current time: %%$clock" [OPER1ASYNC] - Current time: 10:25:35 [C=ASYNCSVC1][I=_I00000001][S=0] (_OPER); OPER1ASYNC; 2; [0]; done<end of module> To Router:chn=725;len=43: ANSWER; typ=Z;av=S;op=Z;ret=0,0; hop=0;dbg=0;pid=16620;tid=1868;qid=0;ins=0;

    Doomic said Besides that; i don't understand why we need to specify a new server in the urouter and reroute it to this server.. the uRouter could also start up a new uServer process with the same server name, can't he?

    No, there (currently) is no logical that allows to auto-magically start a new UServer process. Sorry.

    Doomic said and about the UTIMER... i prefer the /async over the UTIMER... however: after the start of the utimer i placed a sleep of 5 seconds.. while the timer should only wait 2 seconds... so the request was running for a while.. however it didn't get (in this 3 remaining seconds) to the first line of code in the interupt trigger.  

    As I've tried to explain in my last post, by the time the UServer process receives the UTIMER-message the addressed instance does not exist anymore. Here's another excerpt froma log file that shows this:

    [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 8; [0]; activate "UTIMER"."SETMESSAGE"( $instancename , "TEST" , "This is a test" ) [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 9; [0]; activate "UTIMER"."START"( "00:00:05" ) [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 10; [0]; sleep 1000 To Router:chn=1073;len=362: V7ASYNC: typ=10;don=write;ver=2.0;max=4096;met=UTF-8: From Router:chn=1073;len=12: V7ASYNC: typ=10;don=discon;ver=2.0;max=4096;met=UTF-8: [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 11; [0]; done<end of module> [C=DSP1][I=DSP1][S=0] (_setstate); STST; 1; [0]; selectcase $webresponsetype [C=DSP1][I=DSP1][S=0] (_setstate); STST; 2; [0]; case "UPDATE" [C=DSP1][I=DSP1][S=0] (_setstate); STST; 3; [0]; websave [C=DSP1][I=DSP1][S=0] (_setstate); STST; 4; [0]; if ($procerror < 0) [C=DSP1][I=DSP1][S=0] (_setstate); STST; 7; [0]; endif [C=DSP1][I=DSP1][S=0] (_setstate); STST; 24; [0]; endselectcase [C=DSP1][I=DSP1][S=0] (_setstate); STST; 25; [0]; return (0) [C=DSP1][I=DSP1][S=0] (_OPER); CLEANUP; 1; [0]; putmess "[CLEANUP] - %%$clock" [CLEANUP] - 10:25:45 [C=DSP1][I=DSP1][S=0] (_OPER); CLEANUP; 2; [0]; done<end of module> To Router:chn=669;len=611: ANSWER; typ=Z;av=I;op=Z;ret=0,0; hop=0;dbg=0;pid=0;tid=0;qid=0;ins=0; From Router:chn=669;len=74: POSTMSG; id=TEST;to=DSP1 frm=TCP:localhost+19710|userver9||wasv:DSP1 I've highlighted in bold when the cleanup operation is executed and the instance is deleted. As you can see the asynchronous (UTIMER) message arrives (from the URouter) after that. In case you send the message to a detached service then it will arrive:

    [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 8; [0]; newinstance "SVC2", "SVC2" [C=SVC2][I=SVC2][S=0] (_OPER); INIT; 1; [0]; putmess "[INIT] - %%$clock" [INIT] - 10:51:56 [C=SVC2][I=SVC2][S=0] (_OPER); INIT; 2; [0]; done<end of module> [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 9; [0]; activate "UTIMER"."SETMESSAGE"( $instancename , "TEST" , "This is a test" ) [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 10; [0]; activate "UTIMER"."START"( "00:00:05" ) [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 11; [0]; activate "UTIMER"."SETMESSAGE"( "SVC2" , "TEST" , "This is a test" ) [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 12; [0]; activate "UTIMER"."START"( "00:00:05" ) [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 13; [0]; sleep 1000 [C=DSP1][I=DSP1][S=0] (_detail); DTLF; 14; [0]; done<end of module> ... [C=DSP1][I=DSP1][S=0] (_OPER); CLEANUP; 1; [0]; putmess "[CLEANUP] - %%$clock" [CLEANUP] - 10:52:07 [C=DSP1][I=DSP1][S=0] (_OPER); CLEANUP; 2; [0]; done<end of module> To Router:chn=865;len=611: ANSWER; typ=Z;av=I;op=Z;ret=0,0; hop=0;dbg=0;pid=0;tid=0;qid=0;ins=0; From Router:chn=865;len=74: POSTMSG; id=TEST;to=SVC2 frm=TCP:localhost+19710|userver9||wasv:DSP1 [C=SVC2][I=SVC2][S=0] (_async); ASYS; 1; [0]; putmess "[%%$instancename][ASYS] - %%$clock: %%$msgid" [SVC2][ASYS] - 10:52:07: TEST [C=SVC2][I=SVC2][S=0] (_async); ASYS; 2; [0]; done<end of module> But, as mentioned before, this is probably not a good idea. I hope this helps. In case you continue to struggle with the asynchronous activate then please feel free to contact support. Kind regards, Daniel


    Author: diseli (daniel.iseli@uniface.com)
  3. I don't understand what i did wrong last time... but it is working now! Still don't like the flow where you have to setup and configure a new userver process... but it is something i can live with. Thank you


    Author: Doomic (m.doorne@amyyon.nl)
  4. Hello, A service can only be executed asynchronously when it's running remotely. For this you need to redirect the service in question in the [SERVICES_EXEC] section of the UServer ASN file (and point it to a different UST/Userver). Something like this: [PATHS] $ASYNC $TCP:host+port|user|pass|async [SERVICES_EXEC] asyncService = $ASYNC:asyncService The UST async of course needs to be defined in the URouter.asn. As for the UTIMER component: when the UTIMER runs in a UServer then the messages are directed to the URouter. By the time the messages can be delivered the addressed instance most likely does not exist anymore (once a web request is finished all the instances created by the request will be deleted). So you would need to create a detached instance that could handle the UTIMER message. I'm, however, not sure if this is a good idea. First of all: if the detached instance in question is not explicitly deleted then the UServer process will not be shutdown (in case e.g. an idle timeout is specified) since it has state (and that is the case as long as any instance is running). Secondly: asynchronous messages will always be sent to the UServer process of a specific UST that registered last with the URouter. So in case multiple UServer process are running with the same UST (e.g. wasv) then the chance is great that the "wrong" UServer process will get the message. At this moment it's not possible to send an asynchronous message to a specific UServer process. Sorry. In your scenario it's probably best to start an asynchronous service on a different UST that executed the non time-critical code. Hope this helps. Daniel


    Author: diseli (daniel.iseli@uniface.com)
  5. Thank you for the reply, I have add a new server to the urouter.asn. Redirect the asyncService to the urouter with the other server name. Took me a while to get this running.. but at the end.. i got my -161 status back!

    ERROR=-161 MNEM= DESCRIPTION=Illegal mixture of sync and async COMPONENT=TESTSERVICE PROCNAME=TESTOPERATION TRIGGER=OPER LINE=534 ADDITIONAL= INSTANCENAME=ASYNCSERVICE(EXTERN:0X00000007) OPERATIONNAME=ASYNCOPERTATION

    Besides that; i don't understand why we need to specify a new server in the urouter and reroute it to this server.. the uRouter could also start up a new uServer process with the same server name, can't he?   and about the UTIMER... i prefer the /async over the UTIMER... however: after the start of the utimer i placed a sleep of 5 seconds.. while the timer should only wait 2 seconds... so the request was running for a while.. however it didn't get (in this 3 remaining seconds) to the first line of code in the interupt trigger.


    Author: Doomic (m.doorne@amyyon.nl)
  6. I believe when I investigated this a while ago, I couldn't get the userver.exe to start an async process no matter what I did. (Re-routing or otherwise).  Has it changed recently? 


    Author: Iain Sharp (i.sharp@pcisystems.co.uk)