Developing for asynchronous requests
You can develop a CICS® application using the asynchronous API commands to start one or more child tasks and fetch responses from them. When you develop applications for use with the asynchronous API, you will need to consider the flow of the asynchronous API commands and the available options for each command. Channel handling must also be considered if you want to pass input or receive responses as part of an asynchronous request.
Using the TIMEOUT and NOSUSPEND options on the FETCH CHILD and FETCH ANY commands, you have more control over parent-child behavior, making it even easier to reach response time requirements with asynchronous applications.
Programming considerations and recommendations
Here are some practical guidance and recommended approaches on using the CICS asynchronous API. However, your environments and applications might vary and benefit from different approaches. For details, see the IBM® Redbooks® publication IBM CICS Asynchronous API: Concurrent Processing Made Simple.
- Child tasks should perform GETs of data and leave UPDATEs to the parent task.
- Parent and child tasks are separate units of work (UOW). If, for example, a parent abends, it can back-out its own work but will be unconnected from the execution of the child tasks. If the child tasks are limited to GET actions, they can be safely discarded without compromising the state of the data. It is possible for child tasks to perform UPDATEs on data. However, you might be required to code compensation logic to revert changes, if the need arises.
- Allow the same parent program to run and fetch child tasks.
- For manageability, the parent program that begins a child task should remain the program that
fetches the results from the child task. This process is particularly useful if you are using the
FETCH ANY command, because it can become difficult to match the RUN
TRANSID to FETCH ANY commands if they reside in different programs.
Also note that fetched channels are scoped to a link level. So passing results can be problematic if
it is not the parent that fetches the child's results.Tip: If you want to retrieve response data from a child task, specify CHANNEL in EXEC CICS RUN TRANSID even if you have no input data to the child task.
- Long-running parents should use the FREE CHILD command.
- In a long-running parent application, there can be a build-up to control blocks as child tasks complete. In addition, there can be a build-up of sizeable channel data. Without task termination, the CICS system cannot safely discard this data. It is advisable that a long-running parent task deletes any fetched channels and issues FREE CHILD commands against child tasks that are no longer required.
- Keep track of fetched channels.
- Data is passed between parent and child tasks using CICS channel and containers. To return data from a child, the child task updates containers on its current channel. During the termination of child tasks, the channel is managed or owned by the CICS AS domain. The parent task can retrieve the child’s channel by specifying the CHANNEL parameter on the FETCH CHILD or FETCH ANY commands. This approach is more active than a simple inquiry. The channel will bind to the issuing parent.
- Review MAXTASK and set transaction classes.
- The simplicity of the asynchronous API might generate more transactions in a CICS system. It's recommended to review the MAXTASK parameter setting. It is advised to have controls in place to limit the amount of work that a region accepts that cause tasks to be run asynchronously.
- Parameterize timeouts.
- In many cases, the results of a child are needed for the parent to continue their business
logic. If you require a timeout, or if there is a possibility that you might need to in future, you
can code the parent to specify a TIMEOUT parameter on the FETCH
command. The value of the timeout should be parameterized, such as being read from a file or
database table, earlier in the application. By inserting the TIMEOUT parameter and
parameterizing the TIMEOUT value, you prevent the need for a future code update or
recompilation.You can use TIMEOUT and NOSUSPEND on your FETCH CHILD and FETCH ANY commands to improve application versatility and meet business needs in a variety of situations:
- For any child tasks from which you will definitely need a response, use FETCH without TIMEOUT or NOSUSPEND.
- For child tasks from which you need the response in a timely fashion, specify a TIMEOUT value on your FETCH command.
- For child tasks where no response is acceptable, specify NOSUSPEND on your FETCH command.
Examples
Example: A credit card application
In this example, a credit card application is used to demonstrate how the commands can be used.
- Start the credit check child tasks
-
- Put the customer details onto a new channel:.
EXEC CICS PUT CONTAINER('CUSTDETAILS') CHANNEL(customerDetails)
- Call the first credit check service with a channel:
EXEC CICS RUN TRANSID('CRD1') CHILD(creditCheck1_tkn) CHANNEL(customerDetails)
- Call the second credit check service with the same channel:
EXEC CICS RUN TRANSID('CRD2') CHILD(creditCheck2_tkn) CHANNEL(customerDetails)
A parent program can continue with other processing after issuing an EXEC CICS RUN TRANSID command, and can issue an EXEC CICS FETCH command at any point afterward to retrieve the results of a child task.
- Put the customer details onto a new channel:.
- Get a response from a specific child task
-
- Fetch the response from the first
child:
EXEC CICS FETCH CHILD(creditCheck1_tkn) CHANNEL(credReply1_chan) COMPSTATUS(credReply1_status)
In this case, parent processing is blocked until the child task returns a result. Use of the optional parameters NOSUSPEND and TIMEOUT can prevent or limit blocking as preferred.
- Check the response code of the EXEC CICS FETCH CHILD command to ensure the command executed normally.
- If the EXEC CICS FETCH CHILD command executed normally, then check the
COMPSTATUS
of the child to ensure it completed successfully.- If
COMPSTATUS
indicates that the child task completed successfully, then get the response from the reply channel.EXEC CICS GET CONTAINER('RESULT') CHANNEL(credReply1_chan)
- If
COMPSTATUS
indicates that the child task abended, then the logic of the parent application should decide what to do. CICS will clean up all resources when the parent transaction completes.
- If
- Repeat steps 1 through 3 for the second child task.
- Fetch the response from the first
child:
- Get a response from any completed child task
-
It's also possible to fetch a response from any completed child task using the EXEC CICS FETCH ANY command, which will return the result of whichever child task completed first:
EXEC CICS FETCH ANY(creditCheck_tkn) CHANNEL(credReply_chan) COMPSTATUS(credReply_status)
Check the completion of the FETCH ANY command and the child's
COMPSTATUS
as normal. - Free a child
-
As part of your parent task, you can choose to free child tasks, which will tidy up the associated resources and keep system storage use to a minimum, which is especially useful for long-running parent tasks. If, for example, you started three child tasks, but only need the results of one, then you can clean up the remaining two child tasks using FREE CHILD.
EXEC CICS FREE CHILD(creditCheck1_tkn) EXEC CICS FREE CHILD(creditCheck2_tkn)
Command | Optional parameter | Usage |
---|---|---|
EXEC CICS RUN TRANSID | CHANNEL | Use it to:
|
RESP | Use it to see if a command executed successfully | |
EXEC CICS FETCH commands | CHANNEL | Use it to receive data from a child task, as long as a channel was supplied on the initial RUN TRANSID command. |
NOSUSPEND | Use it to stop a FETCH command from blocking: the command will return
immediately regardless of whether a child task has completed. If the child task has finished when the command is issued, the command will return immediately with a NORMAL response. If the child hasn’t finished, the NOTFINISHED condition will occur with RESP2 value of 52. |
|
TIMEOUT | Use it to make a FETCH command wait for a specified amount of time before
returning. You can specify the maximum time in milliseconds that the parent task will wait for a child task to complete. When TIMEOUT is specified with a non-zero value, the parent task will not be subject to DTIMOUT. If the child task finishes before TIMEOUT is reached, the command will return immediately. If the child task hasn’t finished before TIMEOUT is reached, a NOTFINISHED condition will occur with a RESP2 value of 53. |
|
ABCODE | If COMPSTATUS indicates that a child has abended, then ABCODE will contain the abend code of the child. |
Example: Passing the child token to a linked program to fetch response from the child task
The following steps are an example of how input and output are passed between parent and child tasks using channels.
- The parent task,
PROGP1
, passes input to a child task in a channel, and then links it to a local programPROGP2
.EXEC CICS PUT CONTAINER('REQ') FROM(REQUEST) CHANNEL('ASYNC-CHANNEL') EXEC CICS RUN TRANSID('CHLD') CHANNEL('ASYNC-CHANNEL') CHILD(CHILD-TOKEN) EXEC CICS PUT CONTAINER('CHILDTOKEN') FROM(CHILD-TOKEN) CHANNEL('ASYNC-CHANNEL') EXEC CICS LINK PROGRAM('PROGP2') CHANNEL('ASYNC-CHANNEL')
A copy of the
ASYNC-CHANNEL
created by the parent is passed to the child, and the copy becomes the current channel for the child's initial program. The name of the channel is retained by the copying process, so if the child programPROGC1
issued EXEC CICS ASSIGN CHANNEL thenASYNC-CHANNEL
would be returned. - The child task, with transaction ID
CHLD
and programPROGC1
, gets the input from its current channel:EXEC CICS GET CONTAINER('REQ')
The child will then continue with its logic, generate a response for the parent task, and then put it into a container within its current channel:
EXEC CICS PUT CONTAINER('RESP') FROM(RESPONSE) EXEC CICS RETURN
- The parent task,
PROGP2
, fetches the child response and continues with some business logic before returning toPROGP1
:EXEC CICS GET CONTAINER ('CHILDTOKEN') INTO(CHILD-TOKEN) EXEC CICS FETCH CHILD(CHILD-TOKEN) CHANNEL (FETCHED-CHANNEL) EXEC CICS GET CONTAINER('RESP') CHANNEL(FETCHED-CHANNEL)
When the parent task fetches the response channel from the child, CICS generates a unique channel name and binds the channel to the current program link level. In this example, the fetched channel will be owned by
PROGP2
. WhenPROGP2
returns toPROGP1
, the fetched channel will be deleted by CICS. A child's response channel can only be fetched once by the parent task.
Example: CICS Asynchronous API Fetch variation
This COBOL example has a parent program ASYNCPG1 to demonstrate the use of EXEC CICS FETCH commands with and without option TIMEOUT or NOSUSPEND. The application also have four child programs: ASYNCCH1, ASYNCCH2, ASYNCCH3, ASYNCCH4.
- The parent program needs the response from the first child, so use FETCH
CHILD with no SUSPEND or TIMEOUT
option.
EXEC CICS FETCH CHILD(CHLDTOKN1) CHANNEL(CHLDCHNL1) COMPSTATUS(CVDA) RESP(W-RESP) RESP2(W-RESP2) END-EXEC.
- The parent program can wait for up to 1000 milliseconds when fetching the response from the
second child, so use FETCH CHILD
TIMEOUT.
whereEXEC CICS FETCH CHILD(CHLDTOKN2) CHANNEL(CHLDCHNL2) TIMEOUT(TIMEOUT1) COMPSTATUS(CVDA) RESP(W-RESP) RESP2(W-RESP2) END-EXEC.
TIMEOUT1
is defined as shown below and can be changed dynamically in the program or by reading from a file or database to suit your environment:01 TIMEOUT1 PIC S9(8) USAGE BINARY VALUE 1000.
- For the third and fourth children, the parent program can have any result, but can't afford to
wait, so use FETCH CHILD
NOSUSPEND.
EXEC CICS FETCH ANY(ANYTOKN) CHANNEL(ANYCHNL) NOSUSPEND COMPSTATUS(CVDA) RESP(W-RESP) RESP2(W-RESP2) END-EXEC.