Managing asynchronous operations

Definition

Because an operation is stateless and handles a list of parameters, it is possible to launch it asynchronously. When this happens:

To allow the user to control the asynchronous running task, a set of APIs is available and described below.

The Context of execution

An operation is stateless. The code that is executed during the operation run has access to this, but the instance is empty. However, it can be filled using the AREAD or AINIT method. The parameters sent when calling the method are available as local variables.

Because this execution is asynchronous, the results need to be stored in the database, possibly in log files. When the execution ends, the instance is destroyed.

An asynchronous operation can run silently in the background, but it might be useful for a user to monitor the execution of this task. The user can view details in a dialog box that displays at the top of the page:

This dialog box opens automatically if the operation uses the appropriate API. Information messages can show the progress of the operation. The user can hide and reopen the dialog box by clicking the small icon highlighted in the red square.

An Abort link is also present, and an API allows the developer to check periodically if the execution has stopped.

When the operation is finished, the Abort link is replaced with a Download link. The user can download a file published by an API that could include a log file or any other results.

APIs available to control the execution

The following APIs, which are available to control the execution of asynchronous tasks, are all subprograms located in the same library.

Library ASYRASYNC

Call ASYNCTRACK

This call creates the dialog box if it doesn't already exist, and displays a message with the phase name and phase detail. A completion percentage can also be shown.

The parameters are the following:

CodeType and dimensionContents
CONTEXTACTX instanceCurrent context.
PAHASE_NAMECharCurrent phase to be dispayed.
PHASE_DETAILCharCurrent detail to be displayed.
PERCENTIntegerProgression percentage in the range 0-100.

Func ABORTREQUEST

This function checks if the user requests the task to be aborted. It returns '0' if no abort request was sent, and '1' otherwise.

The parameters are the following:

CodeType and dimensionContents
CONTEXTACTX instanceCurrent context.

Call ADDDIAGNOSE

This call adds a line in the text displayed in the bottom of the panel, in the diagnostics list.

The parameters are the following:

CodeType and dimensionContents
CONTEXTACTX instanceCurrent context.
DIAGNOSE_TEXTCharDiagnose text.
DIAGNOSE_STATUSIntegerStatus value as operation return them (can be CST_ASUCCESS, CST_AINFO or CST_AERROR).

Call LINKDOWNLOAD

This call adds a download link to a file that has been placed in a standard volume.

The parameters are the following:

CodeType and dimensionContents
CONTEXTACTX instanceCurrent context.
DATA_TYPECharcontent type that describes the format of the downloadable file.
PATHCharThe fila path on a standard volume (for instance, "[MYVOL]/myfile.tra", whre [MYVOL] has been defined in the "a href="../administration-reference/supervisor-administration-volumes.md">volume table.

Example

# This example is not based on the standard tables described in Sage X3.# Let's imagine a link on the COUNTRY representation (class COUNTRY), that allows you # to trigger a method that posts all the invoices in an accounting system not yet accounted for # and addressed to customers who are located in the corresponding country.# The current currency instance is CURRENCY.# The parameter sent is the current country (called COUNTRY).# The invoice (main table INVOICE) has a CUSTOMER reference column, a POSTED column (0 if not posted).# The INVOICE class has a POST_IT method.# Extract from script associated to the COUNTRY class:$METHODSCase AMETHODWhen "POST" : Gosub POST_COUNTRY...EndcaseReturn...$POST_COUNTRY# Miscellaneous declarationsLocal File CUSTOMER [CUST]Local File INVOICES [INV]Local Instance CUR_INV using INVOICELocal Instance MYLOG Using C_ALOGLocal Integer OKLocal Char LOGFILE_NAME(100)# Let's generate the country classOK=Fmet this.AREAD([L]COUNTRY)If OK <> [V]CST_AOK : End : Endif# Let's generate a class to generate the logMYLOG=NewInstance C_ALOG AllocGroup Null# Open the log fileOK=fmet MYLOG.ABEGINLOG("Invoice posting")LOGFILE_NAME=fmet MYLOG.AGETNAME# How many invoices ?Local Integer INV_COUNT, CUST_COUNT, INV_NUMBERLink [INV] with [CUST]CUSTKEY=[INV]CUSTOMER As [JOIN] Where [CUST]COUNTRY=this.COUNTRY and [INV]POSTED=0& Order By Key CUSTDATE=[CUST]CUSTKEY;[INV]INVDATEINV_NUMBER=rowcount([JOIN])# Let's perform a double loop on invoicesFor [JOIN]CUSTDATE(1)CUST_COUNT+=1For [JOIN]CUSTDATE# Let's update the asynchronous box for every invoiceCall ASYNCTRACK(this.ACTX,& "Managing customer"-[CUST]NAME,& "Invoice"-[INV]INVNUM,& int(100*(INV_COUNT/INV_TOTAL))) From ASYRASYNC# Let's call the invoices method to generate and post itCURINVOICE = NewInstance INVOICE AllocGroup nullOK=fmet CURINVOICE.AREAD([INV]INVNUM)If OK<>[V]CST_AOKCall ADDDIAGNOSE(this.ACTX,"Error on invoice"-[INV]INVNUM-"reading",OK) From ASYRASYNCElseOK=Fmet CURINVOICE.POST_ITIf OK=[V]CST_AOKOK=fmet MYLOG.APUTLINE("Invoice"-[INV]INVNUM-"successfully posted",OK)EndifEndifINV_COUNT+=1FreeInstance CURINVOICENext# Check if the user wants to stop only when a complete customer has finishedIf func ASYRASYNC.ABORTREQUESTED(this.ACTX)Call ADDDIAGNOSE(this.ACTX,"Interruption. "-num$(INV_COUNT)-"invoices posted",[V]CST_AWARN) From ASYRASYNCBreakEndifNext# Now the generation is completeOK=fmet MYLOG.APUTLINE(num$(INV_COUNT)-"invoices(s) successfully posted for"-num$(CUST_COUNT)-"customers",[V]CST_AOK)OK=fmet MYLOG.AENDLOG # Let's allow the log file (in [TRA] volume) to be downloaded Call ADDLINKDOWNLOAD(this.ACTX,"ATYPE7","[TRA]/"+LOGFILE_NAME) From ASYRASYNCFreeGroup MYLOGEnd

Note

Using these API is of course important if the operation is defined as Asynchronous in the link definition of the representation. But if the operation is described as synchronous, the previous calls will not cause an error: they will simply do nothing. This means that the design of the script associated with a task that might be called in asynchronous mode does not need to be tested if it is the case or not.