diff --git a/docs/docs/configuration/systask.md b/docs/docs/configuration/systask.md index f5061dc40e..ab62f9aac5 100644 --- a/docs/docs/configuration/systask.md +++ b/docs/docs/configuration/systask.md @@ -517,9 +517,20 @@ This is particularly helpful in running simple evaluations in Conductor server, **Parameters:** -|name|description|Notes| +|name|type|description|notes| +|---|---|---|---| +|scriptExpression|String|Javascript (`Nashorn`) evaluation expression defined as a string. Must return a value.|Must be non-empty.| + +Besides `scriptExpression`, any value is accessible as `$.value` for the `scriptExpression` to evaluate. + +**Outputs:** + +|name|type|description| |---|---|---| -|scriptExpression|Javascript (`Nashorn`) evaluation expression defined as a string. Must return a value.|Must be non-empty String.| +|result|Map|Contains the output returned by the `scriptExpression`| + +The task output can then be referenced in downstream tasks like: +```"${lambda_test.output.result.testvalue}"``` **Example** ``` json @@ -534,9 +545,6 @@ This is particularly helpful in running simple evaluations in Conductor server, } ``` -The task output can then be referenced in downstream tasks like: -```"${lambda_test.output.result.testvalue}"``` - ## Terminate Task @@ -546,10 +554,16 @@ For example, if you have a decision where the first condition is met, you want t **Parameters:** -|name|description|Notes| +|name|type|description|notes| +|---|---|---|---| +|terminationStatus|String|can only accept "COMPLETED" or "FAILED"|task cannot be optional| +|workflowOutput|Any|Expected workflow output|| + +**Outputs:** + +|name|type|description| |---|---|---| -|terminationStatus|can only accept "COMPLETED" or "FAILED"|task cannot be optional| -|workflowOutput|Expected workflow output|| +|output|Map|The content of `workflowOutput` from the inputParameters. An empty object if `workflowOutput` is not set.| ```json { @@ -620,84 +634,186 @@ The task is marked as ```FAILED``` if the message could not be published to the ## Do While Task -Do While Task allows tasks to be executed in loop until given condition become false. Condition is evaluated using nashorn javascript engine. -Each iteration of loop over task will be scheduled as taskRefname__iteration. Iteration, any of loopover task's output or input parameters can be used to form a condition. -Do while task output number of iterations with iteration as key and value as number of iterations. Each iteration's output will be stored as, iteration as key and loopover task's output as value -Taskname which contains arithmetic operator must not be used in loopCondition. Any of loopOver task can be reference outside do while task same way other tasks are referenced. -To reference specific iteration's output, ```$.LoopTask['iteration]['first_task']``` -Do while task does NOT support domain or isolation group execution. Nesting of DO_WHILE task is not supported. Loopover task must not be reused in neither workflow nor another DO_WHILE task. +Sequentially execute a list of task as long as a condition is true. The list of tasks is executed first, before the condition is +checked (even for the first iteration). + +When scheduled, each task of this loop will see its `taskReferenceName` concatenated with `__i`, with `i` being the +iteration number, starting at 1. Warning: `taskReferenceName` containing arithmetic operators must not be used. +Each task output is stored as part of the `DO_WHILE` task, indexed by the iteration value (see example below), allowing +the condition to reference the output of a task for a specific iteration (eg. ```$.LoopTask['iteration]['first_task']```) + +The `DO_WHILE` task is set to `FAILED` as soon as one of the loopTask fails. In such case retry, iteration starts from 1. + +Limitations: + - Domain or isolation group execution is unsupported; + - Nested `DO_WHILE` is unsupported; + - `SUB_WORKFLOW` is unsupported; + - Since loopover tasks will be executed in loop inside scope of parent do while task, crossing branching outside of DO_WHILE + task is not respected. Branching inside loopover task is supported. **Parameters:** -|name|description| -|---|---| -|loopCondition|condition to be evaluated after every iteration| -|loopOver|List of tasks that needs to be executed in loop.| +|name|type|description| +|---|---|---| +|loopCondition|String|Condition to be evaluated after every iteration. This is a Javascript expression, evaluated using the Nashorn engine. If an exception occurs during evaluation, the DO_WHILE task is set to FAILED_WITH_TERMINAL_ERROR.| +|loopOver|List[Task]|List of tasks that needs to be executed as long as the condition is true.| + +**Outputs:** + +|name|type|description| +|---|---|---| +|iteration|Integer|Iteration number: the current one while executing; the final one once the loop is finished| +|`i`|Map[String, Any]|Iteration number as a string, mapped to the task references names and their output.| +|*|Any|Any state can be stored here if the `loopCondition` does so. For example `storage` will exist if `loopCondition` is `if ($.LoopTask['iteration'] <= 10) {$.LoopTask.storage = 3; true } else {false}`| **Example** +The following definition: ```json { - "name": "Loop Task", - "taskReferenceName": "LoopTask", - "type": "DO_WHILE", + "name": "Loop Task", + "taskReferenceName": "LoopTask", + "type": "DO_WHILE", + "inputParameters": { + "value": "${workflow.input.value}" + }, + "loopCondition": "if ( ($.LoopTask['iteration'] < $.value ) || ( $.first_task['response']['body'] > 10)) { false; } else { true; }", + "loopOver": [ + { + "name": "first task", + "taskReferenceName": "first_task", "inputParameters": { - "value": "${workflow.input.value}" + "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" + } + ], + "startDelay": 0, + "optional": false +} +``` + +will produce the following execution, assuming 3 executions occurred (alongside `first_task__1`, `first_task__2`, `first_task__3`, +`second_task__1`, `second_task__2` and `second_task__3`): + +```json +{ + "taskType": "DO_WHILE", + "outputData": { + "iteration": 3, + "1": { + "first_task": { + "response": {}, + "headers": { + "Content-Type": "application/json" + } }, - "loopCondition": "if ( ($.LoopTask['iteration'] < $.value ) || ( $.first_task['response']['body'] > 10)) { false; } else { true; }", - "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" + "second_task": { + "response": {}, + "headers": { + "Content-Type": "application/json" } - ], - "startDelay": 0, - "optional": false + } + }, + "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" + } + } } + } +} ``` -If any of loopover task will be failed then do while task will be failed. In such case retry will start iteration from 1. TaskType SUB_WORKFLOW is not supported as a part of loopover task. Since loopover tasks will be executed in loop inside scope of parent do while task, crossing branching outside of DO_WHILE task will not be respected. Branching inside loopover task will be supported. -In case of exception while evaluating loopCondition, do while task will be failed with FAILED_WITH_TERMINAL_ERROR. ## JSON JQ Transform Task JSON JQ Transform task allows transforming a JSON input to another JSON structure using a query expression. -The input for the query (`.`) will be the `inputParameters` of the task. +Check the [Jq manual](https://stedolan.github.io/jq/manual/v1.5/), and the [Jq playground](https://jqplay.org/) +for more information. -For JQ playground go to https://jqplay.org/ +Limitations: + - The java implementation support most, but not all jq functions. See [the lib](https://github.com/eiiches/jackson-jq) for details. **Parameters:** -|name|description| -|---|---| -|queryExpression|JQ query expression +|name|type|description| +|---|---|---| +|queryExpression|String|JQ query expression. Input is the entire `inputParameters` object.| + +**Outputs:** + +|name|type|description| +|---|---|---| +|result|Any|First result returned by the jq expression| +|resultList|List[Any]|List of all results returned by the jq expression| +|error|String|Error, if the query throws an error.| **Example** +The following definition: ```json - { - "name": "jq_1", - "taskReferenceName": "jq_1", - "type": "JSON_JQ_TRANSFORM", - "inputParameters": { +{ + "name": "jq_1", + "taskReferenceName": "jq_1", + "type": "JSON_JQ_TRANSFORM", + "inputParameters": { + "in1": { + "arr": [ "a", "b" ] + }, + "in2": { + "arr": [ "c", "d" ] + }, + "queryExpression": "{ out: (.in1.arr + .in2.arr) }" + } +} +``` + +will produce the following execution: + +```json +{ + "name": "jq_1", + "type": "task-execution", + "taskReferenceName": "jq_1", + "taskType": "JSON_JQ_TRANSFORM", + "inputData": { "in1": { "arr": [ "a", "b" ] }, @@ -705,15 +821,20 @@ For JQ playground go to https://jqplay.org/ "arr": [ "c", "d" ] }, "queryExpression": "{ out: (.in1.arr + .in2.arr) }" - } + }, + "outputData": { + "result": { + "out": ["a","b","c","d"] + }, + "resultList": [ + { + "out": ["a","b","c","d"] + } + ] + } } ``` -In the example above the value of `jq_1.output.result` will be `{ "out": ["a","b","c","d"] }` - -The task output can then be referenced in downstream tasks like: -`"${jq_1.output.result.out}"` - ## Set Variable Task @@ -740,4 +861,4 @@ The parameters for this task are the variable names with their respective values } ``` -Later in that workflow, the variable can be referenced by `"${workflow.variables.stage}"` \ No newline at end of file +Later in that workflow, the variable can be referenced by `"${workflow.variables.stage}"`