A typical FlowForce job returns a result only after all processing steps have finished, assuming that no error has been encountered. As long as there are running steps, the job must wait for them to finish before returning the result. For jobs configured as Web services, this means that the HTTP transaction must be kept open for the entire duration of the job execution, which may take several minutes or even hours in some cases, depending on the volume of processed data. To handle such cases more efficiently, you can create postponed steps.
Postponed steps take place only after all non-postponed steps have been processed and the job has returned a result. Even though a job with postponed steps might return a result early, the job is considered in progress until the execution of all postponed steps has finished. The job is considered to have finished successfully if all its postponed steps have finished successfully as well.
You can create postponed steps anywhere in the job where a step is allowed. To do this, create a new job or open an existing one, then click the new Postpone step button in the Execution steps section. Click inside the Postpone sequence to create a step that is to be postponed. You can create multiple postponed steps. This could be important for error handling: If an error occurs within a postponed sequence, the others will not be affected. You can also nest postponed sequences.
A job may contain multiple postponed sequences at various places in the job. When an error occurs in a postponed step, the general rules are as follows:
•If a postponed step encounters an error, the step will be canceled, along with any subsequent steps in the same postponed sequence, and the error will be logged. Note that this affects only the current sequence. If there are other postponed sequences in the same job, they will continue to run.
•If a postponed step within a protected block encounters an error, all postponed steps that are part of that block will be canceled.
The example below illustrates a possible scenario in which postponed steps might be useful. This job is run as a Web service and can be invoked at any time by a client, including from the browser. For details about such jobs, see Jobs as Web Services.
Step A runs a time-consuming shell command that lists recursively all the directories and files within a large system directory. For this reason, Step A is defined as a postponed step. Step B takes the standard output (stdout) produced by A and writes it to a file. Step B depends on the output produced by Step A and, therefore, has to be part of the postponed sequence, too. Step C informs callers of the service that the task has been submitted successfully. Whenever the Web service is called, the steps above will run in the following order: C, A, B. The reason for that is that A and B are postponed steps, so C is executed first.
The advantage of this configuration is that the job returns the result immediately after running Step C, and the HTTP transaction can end, freeing up server resources for other requests. After returning the result of the job, FlowForce will go on to run postponed Steps A and B.
When you invoke the job above in your browser, the message Task has been submitted successfully will be displayed in the browser, while the job continues running until it creates output.txt. If neither A nor B fails, the output file will be created at the following path: C:\FlowForce\Postponed\output.txt.
Important
In our example, Step C has to be the last one in the job because the step outputs the result to the browser.
If you move Step C to the very top, it is still executed first, and Step B is still the last to be executed. However, this would change the job result, and the browser would display some empty output similar to [].
The reason is that the result of a job is always the result of the last executed step. Postponed steps do not have a return value but produce an empty sequence instead. |
A job may contain multiple postponed steps and multiple sequences of postponed steps. The subsections below describe some of the possible scenarios.
The sample job below will run in the following order: A, C, B, D. The non-postponed steps are executed first, followed by the postponed steps. Step C returns a result.
A
postpone B
C
postpone D
You can also add postponed steps to conditions (Choose steps). In this case, the postponed step will be run only if the respective when or otherwise branch is run as well.
when expression=true
{
postpone A
B
C
}
otherwise
{
postpone D
E
F
}
In this job, if the expression is true, the steps will run in the following order: B, C*, A. Otherwise, the run order will be: E, F*, D. The asterisks indicate steps that return results.
The sample job below shows a for each step, in which the postponed steps will be processed after the non-postponed steps, in the same order as in the loop they are part of.
for each item in list
{
A
postpone B
}
For example, if the loop runs three times, the steps above will run in the following order: A1, A2, A3*, B1, B2, B3. The digits indicate loop numbers. The asterisk indicates a step that returns a result.
You can also nest postponed steps within other postponed steps (see code listing below). In this case, outer steps of the same depth are processed first, and the nested postponed steps will be executed only after their parent sequence has finished. In our sample job, the steps will run in the following order: A, G, N, B, D, F, C, E, H, K, M, J, L. Step N returns a result.
A
postpone
[
B
postpone C
D
postpone E
F
]
G
postpone
[
H
postpone J
K
postpone L
M
]
N
If you need to create and test advanced configurations like the one above, you can always track the execution order of steps in the log.