Try OpenEdge Now
skip to main content
Developing AppServer Applications
Programming ABL Client Applications : Managing asynchronous requests : Cancelling asynchronous requests after a specified time limit : Examples
 
Examples
The following simple example uses the CANCEL-REQUESTS-AFTER( ) method:
DEFINE VARIABLE hSrv AS HANDLE  NO-UNDO.
DEFINE VARIABLE bool AS LOGICAL NO-UNDO.

CREATE SERVER hSrv.
hSrv:CONNECT("-URL AppServerDC://hostName/svc").

bool = hSrv:CANCEL-REQUESTS-AFTER(30).
RUN foo.p ON SERVER hSrv ASYNCHRONOUS ("Hello World").

WAIT-FOR WINDOW-CLOSE OF CURRENT-WINDOW.
The following is a server program used in the previous example to demonstrate the STOP-AFTER phrase:
/* srvrNested3.p */
DEFINE INPUT-OUTPUT PARAMETER p1 AS CHARACTER NO-UNDO.

DEFINE VARIABLE srvrTimeLimit AS INTEGER NO-UNDO INITIAL 10.
DEFINE VARIABLE spinLimit     AS INT64   NO-UNDO INITIAL 15000.

p1 = FILL("Y", 30). /* 30 "Y" characters will be sent to the client */

DO STOP-AFTER srvrTimeLimit:
  RUN spinHere (spinLimit).
END.
RETURN "30 Ys".

PROCEDURE spinHere:
  DEFINE INPUT PARAMETER spinLimit AS INT64 NO-UNDO.

  DEFINE VARIABLE loopFlag AS LOGICAL NO-UNDO.
  DEFINE VARIABLE endTime  AS INT64   NO-UNDO.

  ASSIGN
    loopFlag = TRUE
    endTime  = ETIME(FALSE) + spinLimit.

  DO WHILE loopFlag:
    IF (ETIME(FALSE) > endTime) THEN
      loopFlag = FALSE.
  END.
END PROCEDURE.
The following is a new example of a client program that asynchronously invokes the server program (srvrNested3.p):
/* clntNested4.p */
DEFINE BUTTON send-button LABEL "SEND".
DEFINE BUTTON close-button LABEL "CLOSE".

DEFINE VARIABLE ah     AS HANDLE    NO-UNDO.
DEFINE VARIABLE cstr   AS CHARACTER NO-UNDO.
DEFINE VARIABLE rcvcnt AS INTEGER   NO-UNDO.
DEFINE VARIABLE sh     AS HANDLE    NO-UNDO.
DEFINE VARIABLE S1     AS CHARACTER NO-UNDO FORMAT "X(30)".
DEFINE VARIABLE S2     AS CHARACTER NO-UNDO FORMAT "X(30)".
DEFINE VARIABLE xmtcnt AS INTEGER   NO-UNDO.

/* =============================================================== */
FORM send-button close-button
  WITH FRAME buttonFrame.

DEFINE FRAME foo
  S1 AT 1 WITH NO-LABELS.

DEFINE FRAME bar
  S2 AT 1 WITH NO-LABELS.
/* =============================================================== */

ON CHOOSE OF send-button DO:
  RUN runRemoteProc.
  S1 = "Ran proc(" + STRING(xmtcnt) + ")".
  DISPLAY S1 WITH FRAME foo 1 DOWN.
  HIDE FRAME bar.
END.

ON CHOOSE OF close-button DO:
  sh:DISCONNECT().
  DELETE OBJECT sh.
  QUIT.
END.

ON WINDOW-CLOSE OF CURRENT-WINDOW DO:
  sh:DISCONNECT().
  DELETE OBJECT sh.
  QUIT.
END.

ENABLE send-button close-button WITH FRAME buttonFrame.

CREATE SERVER sh.
cstr = "-URL AppServerDC://hostname:portnum/svc".
sh:CONNECT(cstr).

WAIT-FOR WINDOW-CLOSE OF CURRENT-WINDOW OR CHOOSE OF close-button.

sh:DISCONNECT().
DELETE OBJECT sh.
/* =============================================================== */

PROCEDURE runRemoteProc:
  DEFINE VARIABLE ix AS CHARACTER NO-UNDO.
  ASSIGN
    xmtcnt = xmtcnt + 1
    ix     = FILL("X", 30).
  sh:CANCEL-REQUESTS-AFTER(10).
  DO STOP-AFTER 5:
    RUN srvrNested3.p ON SERVER sh ASYNCHRONOUS SET ah
      EVENT-PROCEDURE "remoteProcHandler"
      IN THIS-PROCEDURE (INPUT-OUTPUT ix).
  END.
END PROCEDURE.

/* =============================================================== */

PROCEDURE remoteProcHandler:
  DEFINE INPUT PARAMETER ix AS CHARACTER NO-UNDO.

  ASSIGN
    rcvcnt = rcvcnt + 1
    S2     = "remoteProcHandler(" + STRING(rcvcnt)
    S2     = S2 + IF (SELF:STOP) THEN ") STOPPED"
             ELSE IF (SELF:CANCELLED) THEN ") CANCELLED"
             ELSE ") FINISHED".
  DISPLAY S2 WITH FRAME bar 1 DOWN.
  DELETE OBJECT SELF.
END PROCEDURE.
With this local procedure, the CANCEL-REQUESTS-AFTER( ) method is called on the server handle to establish a time limit of 10 seconds for remote asynchronous procedures; if the timer is already active, the time limit is reset to 10 seconds. The srvrNested3.p is run asynchronously on the AppServer from within a block that specifies a time limit of 5 seconds. The remote procedure does not implicitly adopt the 5 second time limit of the local procedure (as would be the case for running a synchronous remote procedure). In this example, the local time limit of 5 seconds is essentially irrelevant, since it only times the RUN statement. Since this is an asynchronous RUN, it returns immediately after sending the request.
If the response to the request returns before 10 seconds has elapsed, the event procedure remoteProcHandler is run.
If the time limit is exceeded before the response returns, the client AVM will call CANCEL-REQUESTS( ) method on the server handle. This will cause a STOP message to be sent to the AppServer running the asynchronous request. As with remote synchronous requests, this will cause the STOP condition to be raised in the server application. Depending on the STOP handling logic in the server application, the STOP condition may be returned to the client application in the response. This is indicated by the STOP attribute in the asynchronous request handle, which is set to TRUE prior to running the event procedure.
It is important to note that the time limit for the asynchronous remote procedure call restarts each time the CANCEL-REQUESTS-AFTER( ) method is called. This effectively extends the time limit for any asynchronous requests that have already been run (or queued to run) on that server handle.
Note: Another way to time limit procedure calls is to set the ubroker property called srvrExecutionTimeLimit will in the [UBroker] section of the ubroker.properties file. This is a non-negative integer property that specifies the maximum time in seconds that a remote procedure may execute on the given AppServer. This timeout value applies to all remote procedures that execute on the AppServer.