Simultaneous asynchronous calls with time limit

Posted by geertjeguns@hotmail.com on 18-Mar-2016 11:02

Hello everyone,

I'm trying to launch 2 asynchronous programs on a server.  

Each program will execute a query on a different DB and at the end return the results.

Both programs have to be executed within a predefined time-frame.  After that time, the result will not be taken into account.  

I'm still having some problems with the wait-for part.  For the moment I'm waiting on my second program.  But how can I wait on both programs and still cancel its execution when the time has passed?

Here is what I have so far:

Main program:

DEFINE VARIABLE hAppServer AS HANDLE NO-UNDO.
DEFINE VARIABLE hAppServer2 AS HANDLE NO-UNDO.
DEFINE VARIABLE hRequest AS HANDLE NO-UNDO.
DEFINE VARIABLE hRequest2 AS HANDLE NO-UNDO.
DEFINE VARIABLE wlOk AS LOGICAL NO-UNDO.
DEFINE VARIABLE wiTimeOut AS INTEGER NO-UNDO INIT 10000.

CREATE SERVER hAppserver.
hAppserver:CONNECT("-AppService assv1 -H localhost","geegun","geegun").

CREATE SERVER hAppserver2.
hAppserver2:CONNECT("-AppService assv1 -H localhost","geegun","geegun").

/* both procedures have to run asynchronous to save time */
RUN proctwo.p ON SERVER hAppserver ASYNCHRONOUS SET hRequest
EVENT-PROCEDURE "procEnd" IN THIS-PROCEDURE (INPUT wiTimeOut, OUTPUT wcText AS CHARACTER, OUTPUT wcStatus AS CHARACTER).

RUN procthree.p ON SERVER hAppserver2 ASYNCHRONOUS SET hRequest2
EVENT-PROCEDURE "procEnd" IN THIS-PROCEDURE (INPUT wiTimeOut, OUTPUT wcText AS CHARACTER, OUTPUT wcStatus AS CHARACTER).

MESSAGE "one"
VIEW-AS ALERT-BOX.

ETIME(TRUE).

/* We wait for a certain time to give the asynchronous programs the time to gather their data */
DO STOP-AFTER wiTimeOut ON STOP UNDO
:
WAIT-FOR PROCEDURE-COMPLETE OF hRequest2.
END.

/* Here comes the code to put all the data into a browser on the screen */


FINALLY:
hAppServer:DISCONNECT().
DELETE OBJECT hAppServer.
hAppserver2:DISCONNECT().
DELETE OBJECT hAppserver2.
END.


PROCEDURE procEnd:
DEFINE INPUT PARAMETER ipcText AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER ipcStatus AS CHARACTER NO-UNDO.

IF ipcStatus = "COMPLETED"
THEN MESSAGE ipcText VIEW-AS ALERT-BOX.

END PROCEDURE.

Program 1 (proctwo.p):

DEFINE INPUT PARAMETER wiTimeOut AS HANDLE NO-UNDO.
DEFINE OUTPUT PARAMETER wcText AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER wcStatus AS CHARACTER NO-UNDO.

DEFINE VARIABLE wii AS INTEGER NO-UNDO.
DEFINE VARIABLE wicount AS INTEGER NO-UNDO.

DO STOP-AFTER wiTimeOut ON STOP UNDO, RETURN ERROR "ERROR"
:
/* Enabling this DO will make this result fail to have a result */
/* DO wii = 1 TO 10: */
FOR EACH signcli NO-LOCK:
wicount = wicount + 1.
END.
/* END. */

ASSIGN wcText = "two"
wcStatus = "COMPLETED"
.
END.

Program 2 (progthree.p):

DEFINE INPUT PARAMETER wiTimeOut AS HANDLE NO-UNDO.
DEFINE OUTPUT PARAMETER wcText AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER wcStatus AS CHARACTER NO-UNDO.

DEFINE VARIABLE wii AS INTEGER NO-UNDO.
DEFINE VARIABLE wicount AS INTEGER NO-UNDO.

DO STOP-AFTER wiTimeOut ON STOP UNDO, RETURN ERROR "ERROR"
:
/* Enabling this DO will make this result fail to have a result */
/* DO wii = 1 TO 10: */
FOR EACH signcli NO-LOCK:
wicount = wicount + 1.
END.
/* END. */

ASSIGN wcText = "three"
wcStatus = "COMPLETED"
.
END.

Kind regards,

Geert Guns

All Replies

Posted by ntwatkins on 18-Mar-2016 12:36

You could use a repeat loop with a PROCESS EVENTS and check to see if each process is still running.  Something like the following pseudo-code:

$repeat-block$:
REPEAT:
   PROCESS EVENTS.
   
   IF <both processes are complete> THEN
      LEAVE $repeat-block$.
END.

To handle your timeout, you could also use the CANEL-REQUESTS-AFTER() method of the server handle.

Posted by Laura Stern on 18-Mar-2016 14:28

If you put that PROCESS EVENTS code on the server, nothing would happen other than spinning your wheels as there are no events to process there.  And you cannot run that and do whatever it is you are really trying to do at the same time.  If you meant to run it on the client, it is not necessary.  The WAIT-FOR is already accomplishing the same thing.

So back to the original question, what do you mean by "makes this fail to have a result"?  Do you mean that it times out?

Also, why are you doing the STOP AFTER on both the client and the server?  

Posted by geertjeguns@hotmail.com on 18-Mar-2016 16:41

By "makes this fail" I mean that it times out.

I put in the STOP AFTER on the server side to force the procedure to stop after a determined time-interval.

When this happens, the status variable will not be set to "completed".  This status variable gives me the option to check if the asynchronous procedure has been completed or not.

I made these programs as some sort of a test case for what we're trying to accomplish in our application.

We are trying to fill a browser by joining data from 2 different external sources:

1) a webservice

2) a external database

Both searches have to be executed simultaneous to save time but within a predefined timeslot (for example: 5 sec).

If for example the webservice would give a timeout or it would take too long, we would only continue with the data retrieved from the external DB and the screen would mention that the data was only retrieved from 1 source.

Posted by Laura Stern on 18-Mar-2016 17:26

Sorry, but I have to ask the obvious 2 questions:

1. What is wTimeout set to?  Are you sure it is in the units you expect.  Sorry, I can't look up right now what time unit it uses.

2. How long does the loop take?  

Posted by geertjeguns@hotmail.com on 18-Mar-2016 18:11

1. the timeout is set to 10 seconds (in this example).  In our application it will most likely be set to about 5 seconds.

2. the loop in the example will take around 30 seconds to complete.  So it will provoke a timeout.

Posted by Laura Stern on 21-Mar-2016 07:50

Ok.  Obviously I've lost sight of your question.  I was fixated on this comment in your code /* Enabling this DO will make this result fail to have a result */ thinking that you were saying this was a problem.  But apparently not.  Looking back your question is this: "For the moment I'm waiting on my second program.  But how can I wait on both programs and still cancel its execution when the time has passed?"

So can you please clarify what the problem is.  Is the 2nd one somehow finishing first and the first is not done or timed out yet when the WAIT-FOR breaks?  

This thread is closed