Do While
The Do While task iterates through a sequence of tasks as long as a given condition is true. The sequence of tasks gets executed before the condition is checked, even for the first iteration, just like a regular do .. while
statement in programming.
Task parameters
Configure these parameters for the Do While task.
Parameter | Description | Required/ Optional |
---|---|---|
evaluatorType | The type of evaluator used. Supported types:
| Required. |
loopCondition | The condition that is evaluated by the Do While task after every iteration. The expression format depends on the evaluator type:
| Required, unless iterating over a list of items. |
loopOver | The list of tasks to be executed as long as the condition is true. | Required. |
inputParameters. items | An array of items, which will be iterated over in the loop. The number of iterations is equal to the list size. You can use this to iterate without a condition. Refer to Examples for more information on how to use the items parameter. | Optional. |
inputParameters. keepLastN | The number of iteration execution data to retain. If enabled, the default value is 2. Use keepLastN if the number of iterations is expected to be large and not all execution data needs to be retained. Refer to Execution data for more information. | Optional. |
Task configuration
This is the task configuration for a Do While task.
{
"name": "do_while",
"taskReferenceName": "do_while_ref",
"inputParameters": {},
"type": "DO_WHILE",
"loopCondition": "", // Condition
"evaluatorType": "value-param",
"loopOver": [ // List of tasks to be executed in the loop
{//taskDefinition},
{//taskDefinition}
]
}
Task output
The Do While task will return the following parameters.
Parameter | Description |
---|---|
iteration | The number of iterations. If the Do While task is in progress, iteration will show the current iteration number. If the Do While task is completed, iteration will show the final number of iterations. |
In addition, an object will be created for each iteration, keyed by its iteration number (eg. 1, 2, 3) and containing the task reference names of all the loop tasks and their outputs.
The output payload may also contain any state stored in loopCondition
. For example, if the loopCondition
is if ($.LoopTask['iteration'] <= 10) {$.LoopTask.storage = 3; true } else {false}
, storage
will exist as an output parameter.
Example output
{
"1": {
"taskA_ref": {
"response": {
"headers": {},
"body": {},
"statusCode": 200
}
},
"taskB_ref": {
//taskBOutput
}
},
"2": {
"taskA_ref": {
"response": {
"headers": {},
"body": {},
"statusCode": 200
}
},
"taskB_ref": {
//taskBOutput
}
},
"iteration": 2
}
Accessing the Do While task output
Each time a task in the do while loop is completed, the output is saved and indexed by the iteration value. This makes it possible for the condition to check the output of a specific task iteration using $.TaskName[’iteration’]['loopTask']
, replacing TaskName
with the actual Do While task reference name and loopTask
with the loop task reference name.
Adding a Do While task in UI
To add a Do While task:
- In your workflow, select the (+) icon and add a Do While task.
- In Script params, add the parameter that will be evaluated in the expression.
- In Loop condition, select the evaluator type and enter the loop condition.
- Value-Param—Ensure that the expression value matches the parameter key you have defined in Script params.
- ECMASCRIPT—Enter a JavaScript script.
- In your workflow, select the (+) icon to add tasks to the do while loop.
- (Optional) If the number of iterations is expected to be large, turn off No Limits to set the number of iteration execution data to retain. By default, there is no limit on the execution data kept if the task size is below 300.
Execution
When a Do While loop is executed, each task in the loop will have its taskReferenceName
concatenated with __i, with i as the iteration number starting at 1. If one of the loop task fails, the Do While task status will be set as FAILED and upon retry the iteration number will restart from 1.
If an exception occurs during evaluation of the loopCondition
, the task is set to FAILED_WITH_TERMINAL_ERROR
.
Execution data
During execution, each iteration execution can be accessed from the dropdown box in the Conductor UI for the Do While task and all its loop tasks.
If keepLastN
is used, the latest n iterations will be retained. In the example below where keepLastN=2
, the latest two iterations are accessible from the dropdown box in the UI.
From v4.1.52 onwards, Do While executions that exceed 300 tasks across its iterations will be summarized, and the Conductor UI will only display the latest two iterations. If required, use keepLastN
to display more iterations.
Examples
Here are some examples for using the Do While task.
Using value-param
evaluator
When using the value-param
evaluator, the input key (such as state
in the example below) must be a boolean value.
{
"name": "do_while",
"taskReferenceName": "do_while_ref",
"inputParameters": {
"state": "${workflow.input.active}"
},
"type": "DO_WHILE",
"loopCondition": "state",
"loopOver": [
{
"name": "http",
"taskReferenceName": "http_ref",
"inputParameters": {
"uri": "https://orkes-api-tester.orkesconductor.com/api",
"method": "GET",
"accept": "application/json",
"contentType": "application/json",
"encode": true
},
"type": "HTTP"
},
{
"name": "wait",
"taskReferenceName": "wait_ref",
"inputParameters": {},
"type": "WAIT"
}
],
"evaluatorType": "value-param"
}
Using graaljs
evaluator
{
"name": "do_while",
"taskReferenceName": "do_while_ref",
"inputParameters": {
"number": "${workflow.input.qty}"
},
"type": "DO_WHILE",
"loopCondition": "(function () {\n if ($.do_while_ref['iteration'] < $.number) {\n return true;\n }\n return false;\n})();",
"loopOver": [
{
"name": "first task",
"taskReferenceName": "first_task",
"inputParameters": {
"http_request": {
"uri": "http://localhost:8082",
"method": "POST"
}
},
"type": "HTTP"
},
{
"name": "second task",
"taskReferenceName": "second_task",
"inputParameters": {
"http_request": {
"uri": "http://localhost:8082",
"method": "POST"
}
},
"type": "HTTP"
}
]
"evaluatorType": "graaljs"
}
When executed successfully, the above Do While task will produce the following execution JSON, assuming three iterations occurred:
{
"taskType": "DO_WHILE",
"outputData": {
"iteration": 3,
"1": {
"first_task": {
"response": {},
"headers": {
"Content-Type": "application/json"
}
},
"second_task": {
"response": {},
"headers": {
"Content-Type": "application/json"
}
}
},
"2": {
"first_task": {
"response": {},
"headers": {
"Content-Type": "application/json"
}
},
"second_task": {
"response": {},
"headers": {
"Content-Type": "application/json"
}
}
},
"3": {
"first_task": {
"response": {},
"headers": {
"Content-Type": "application/json"
}
},
"second_task": {
"response": {},
"headers": {
"Content-Type": "application/json"
}
}
}
}
}
Using the iteration key in a loop task
Sometimes, you may want to use the Do While iteration value/counter inside your loop tasks. In this example, an API call is made to a GitHub repository to get all stargazers and each iteration increases the pagination.
The Do While task’s taskReferenceName
is "get_all_stars_loop_ref". To evaluate the current iteration, the parameter $.get_all_stars_loop_ref['iteration']
is used in the loopCondition
. In the HTTP task embedded in the loop, ${get_all_stars_loop_ref.output.iteration}
is used to define which page of results the API should return.
{
"name": "get_all_stars",
"taskReferenceName": "get_all_stars_loop_ref",
"inputParameters": {
"stargazers": "4000"
},
"type": "DO_WHILE",
"loopCondition": "if ($.get_all_stars_loop_ref['iteration'] < Math.ceil($.stargazers/100)) { true; } else { false; }",
"loopOver": [
{
"name": "100_stargazers",
"taskReferenceName": "hundred_stargazers_ref",
"inputParameters": {
"counter": "${get_all_stars_loop_ref.output.iteration}",
"http_request": {
"uri": "https://api.github.com/repos/conductor-oss/conductor/stargazers?page=${get_all_stars_loop_ref.output.iteration}&per_page=100",
"method": "GET",
"headers": {
"Authorization": "token ${workflow.input.gh_token}",
"Accept": "application/vnd.github.v3.star+json"
}
}
},
"type": "HTTP"
}
]
}
Iterate over a list of items
It is possible to iterate over a list of items. To iterate over a list, the Do-While task MUST have an input parameter specifically named 'items' containing the collection to process. The parameter name 'items' is required and cannot be substituted with another name.
The number of iterations will be equal to the list size. If “items”=[“a”,“b”,“c”]
, the loop tasks will be executed three times; if “items”=[]
, the Do While task will be marked as completed without executing the loop tasks.
Each item in the list is passed into each iteration of the loop task using ${do_while_ref.output.item}
.
{
"name": "do_while",
"taskReferenceName": "do_while_ref",
"inputParameters": {
"items": ["a", "b", "c"]
},
"type": "DO_WHILE",
"loopCondition": "",
"loopOver": [
{
"name": "http",
"taskReferenceName": "http_ref",
"inputParameters": {
"uri": "https://orkes-api-tester.orkesconductor.com/api",
"method": "GET",
"accept": "application/json",
"contentType": "application/json",
"encode": true,
"body": {
"item": "${do_while_ref.output.item}"
},
"headers": {}
},
"type": "HTTP"
}
],
"evaluatorType": "value-param"
}
Limitations
There are several limitations for the Do While task:
- Branching—Within a Do While task, branching using Switch, Fork/Join, Dynamic Fork tasks are supported. However, the Do While task may not execute as expected if the branching crosses outside its scope, since the loop tasks will be executed within the scope.
- Nested loops—Nested Do While tasks are not supported. To achieve a similar functionality as a nested do while loop, you can use a Sub Workflow task inside the Do While task.
- Isolation group execution—Isolation group execution is not supported. However, domain is supported for loop tasks inside the Do While task.