Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
251 changes: 251 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Provides Serverless Workflow language examples
- [New Patient Onboarding (Error checking and Retries)](#New-Patient-Onboarding)
- [Purchase order deadline (ExecTimeout)](#Purchase-order-deadline)
- [Accumulate room readings and create timely reports (ExecTimeout and KeepActive)](#Accumulate-room-readings)
- [Car vitals checks (SubFlow state Repeat)](#Car-Vitals-Checks)

### Hello World Example

Expand Down Expand Up @@ -3241,3 +3242,253 @@ functions:
</td>
</tr>
</table>

### Car Vitals Checks

#### Description

In this example we need to check car vital signs while our car is driving.
The workflow should start when we receive the "carOn" event and stop when the "carOff" event is consumed.
While the car is driving our workflow should repeatedly check the vitals every 2 minutes.

For this example we use the workflow [SubFlow](../specification.md#SubFlow-State) state and its
[repeat definition](../specification.md#Repeat-Definition) to repeat execution of the vitals checks.

#### Workflow Diagram

<p align="center">
<img src="../media/examples/example-checkcarvitals.png" height="550px" alt="Check Car Vitals Example"/>
</p>

#### Workflow Definition

We fist define our top-level workflow for this example:

<table>
<tr>
<th>JSON</th>
<th>YAML</th>
</tr>
<tr>
<td valign="top">

```json
{
"id": "checkcarvitals",
"name": "Check Car Vitals Workflow",
"version": "1.0",
"states": [
{
"name": "WhenCarIsOn",
"type": "event",
"start": true,
"onEvents": [
{
"eventRefs": ["CarTurnedOnEvent"]
}
],
"transition": "DoCarVitalsChecks"
},
{
"name": "DoCarVitalsChecks",
"type": "subflow",
"workflowId": "vitalscheck",
"repeat": {
"stopOnEvents": ["CarTurnedOffEvent"]
},
"end": true
}
],
"events": [
{
"name": "CarTurnedOnEvent",
"type": "car.events",
"source": "my/car/start"
},
{
"name": "CarTurnedOffEvent",
"type": "car.events",
"source": "my/car/start"
}
]
}
```

</td>
<td valign="top">

```yaml
id: checkcarvitals
name: Check Car Vitals Workflow
version: '1.0'
states:
- name: WhenCarIsOn
type: event
start: true
onEvents:
- eventRefs:
- CarTurnedOnEvent
transition: DoCarVitalsChecks
- name: DoCarVitalsChecks
type: subflow
workflowId: vitalscheck
repeat:
stopOnEvents:
- CarTurnedOffEvent
end: true
events:
- name: CarTurnedOnEvent
type: car.events
source: my/car/start
- name: CarTurnedOffEvent
type: car.events
source: my/car/start
```

</td>
</tr>
</table>

And then our reusable sub-workflow which performs the checking of our car vitals:

<table>
<tr>
<th>JSON</th>
<th>YAML</th>
</tr>
<tr>
<td valign="top">

```json
{
"id": "vitalscheck",
"name": "Car Vitals Check",
"version": "1.0",
"states": [
{
"name": "CheckVitals",
"type": "operation",
"start": true,
"actions": [
{
"functionRef": "checkTirePressure"
},
{
"functionRef": "checkOilPressure"
},
{
"functionRef": "checkCoolantLevel"
},
{
"functionRef": "checkBattery"
}
],
"transition": "EvaluateChecks"
},
{
"name": "EvaluateChecks",
"type": "switch",
"dataConditions": [
{
"name": "Some Evaluations failed",
"condition": "$.evaluations[?(@.check == 'failed')]",
"end": {
"produceEvents": [
{
"eventRef": "DisplayFailedChecksOnDashboard",
"data": "{{ $.evaluations }}"
}
]

}
}
],
"default": {
"transition": "WaitTwoMinutes"
}
},
{
"name": "WaitTwoMinutes",
"type": "delay",
"timeDelay": "PT2M",
"end": true
}
],
"events": [
{
"name": "DisplayFailedChecksOnDashboard",
"kind": "produced",
"type": "my.car.events"
}
],
"functions": [
{
"name": "checkTirePressure",
"operation": "mycarservices.json#checktirepressure"
},
{
"name": "checkOilPressure",
"operation": "mycarservices.json#checkoilpressure"
},
{
"name": "checkCoolantLevel",
"operation": "mycarservices.json#checkcoolantlevel"
},
{
"name": "checkBattery",
"operation": "mycarservices.json#checkbattery"
}
]
}
```

</td>
<td valign="top">

```yaml
id: vitalscheck
name: Car Vitals Check
version: '1.0'
states:
- name: CheckVitals
type: operation
start: true
actions:
- functionRef: checkTirePressure
- functionRef: checkOilPressure
- functionRef: checkCoolantLevel
- functionRef: checkBattery
transition: EvaluateChecks
- name: EvaluateChecks
type: switch
dataConditions:
- name: Some Evaluations failed
condition: "$.evaluations[?(@.check == 'failed')]"
end:
produceEvents:
- eventRef: DisplayFailedChecksOnDashboard
data: "{{ $.evaluations }}"
default:
transition: WaitTwoMinutes
- name: WaitTwoMinutes
type: delay
timeDelay: PT2M
end: true
events:
- name: DisplayFailedChecksOnDashboard
kind: produced
type: my.car.events
functions:
- name: checkTirePressure
operation: mycarservices.json#checktirepressure
- name: checkOilPressure
operation: mycarservices.json#checkoilpressure
- name: checkCoolantLevel
operation: mycarservices.json#checkcoolantlevel
- name: checkBattery
operation: mycarservices.json#checkbattery
```

</td>
</tr>
</table>
Binary file added media/examples/example-checkcarvitals.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions roadmap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ _Status description:_
| ✔️| Simplified functionRef and transition properties | [spec doc](../specification.md) |
| ✔️| Adding comparison examples with Cadence | [comparison doc](../comparisons/README.md) |
| ✔️| Adding workflow execTimeout and keepActive properties | [spec doc](../specification.md) |
| ✔️| Adding SubFlow state repeat (loop) ability | [spec doc](../specification.md) |
| 🚩 | JSONPatch transformations | [issue](https://github.com/serverlessworkflow/specification/issues/149) |
| 🚩 | Workflow invocation bindings | |
| 🚩 | CE Subscriptions & Discovery | |
Expand Down
37 changes: 37 additions & 0 deletions schema/workflow.json
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,10 @@
"type": "string",
"description": "Sub-workflow unique id"
},
"repeat": {
"$ref": "#/definitions/repeat",
"description": "SubFlow state repeat exec definition"
},
"stateDataFilter": {
"$ref": "#/definitions/statedatafilter"
},
Expand Down Expand Up @@ -1980,6 +1984,39 @@
}
},
"required": []
},
"repeat": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Expression evaluated against SubFlow state data. SubFlow will repeat execution as long as this expression is true or until the max property count is reached",
"minLength": 1
},
"checkBefore": {
"type": "boolean",
"description": "If true, the expression is evaluated before each repeat execution, if false the expression is evaluated after each repeat execution",
"default": true
},
"max": {
"type": "integer",
"description": "Sets the maximum amount of repeat executions",
"minimum": 0
},
"continueOnError": {
"type": "boolean",
"description": "If true, repeats executions in a case unhandled errors propagate from the sub-workflow to this state",
"default": false
},
"stopOnEvents": {
"type" : "array",
"description": "List referencing defined consumed workflow events. SubFlow will repeat execution until one of the defined events is consumed, or until the max property count is reached",
"minItems": 1,
"items": {
"type": "string"
}
}
}
}
}
}
Loading