diff --git a/.ci/examples-readme-hydration/.gitignore b/.ci/examples-readme-hydration/.gitignore
new file mode 100644
index 00000000..b512c09d
--- /dev/null
+++ b/.ci/examples-readme-hydration/.gitignore
@@ -0,0 +1 @@
+node_modules
\ No newline at end of file
diff --git a/.ci/examples-readme-hydration/index.js b/.ci/examples-readme-hydration/index.js
new file mode 100644
index 00000000..716c640d
--- /dev/null
+++ b/.ci/examples-readme-hydration/index.js
@@ -0,0 +1,38 @@
+const fs = require('fs');
+const path = require('path');
+const YAML = require('yaml');
+
+const examplesPath = path.resolve(__dirname, '../../examples/');
+const readMeTemplatePath = path.resolve(examplesPath, 'README_TEMPLATE.md');
+const readMeOutputPath = path.resolve(examplesPath, 'README.md');
+const extractor = //g;
+const disclaimer = `
+`;
+
+(async () => {
+ let readMe = await fs.promises.readFile(readMeTemplatePath, 'utf8');
+ const includes = readMe.matchAll(extractor);
+ for await(let include of includes) {
+ const fileName = include[1];
+ const format = include[2];
+ let fileContent = await fs.promises.readFile(path.resolve(examplesPath, fileName), 'utf8');
+ if (format === 'yaml') {
+ try {
+ const schema = JSON.parse(fileContent);
+ fileContent = YAML.stringify(schema);
+ }
+ catch(ex) {
+ console.error('Enable to parse JSON or convert it to YAML, output as it is.', ex);
+ }
+ }
+ readMe = readMe.replace(include[0], fileContent);
+ };
+ await fs.promises.writeFile(readMeOutputPath, disclaimer + readMe, { encoding: 'utf8', flag: 'w' });
+})();
\ No newline at end of file
diff --git a/.ci/examples-readme-hydration/package-lock.json b/.ci/examples-readme-hydration/package-lock.json
new file mode 100644
index 00000000..f2b43996
--- /dev/null
+++ b/.ci/examples-readme-hydration/package-lock.json
@@ -0,0 +1,24 @@
+{
+ "name": "examples-readme-hydration",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "examples-readme-hydration",
+ "version": "0.1.0",
+ "license": "ISC",
+ "dependencies": {
+ "yaml": "^2.3.4"
+ }
+ },
+ "node_modules/yaml": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
+ "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
+ "engines": {
+ "node": ">= 14"
+ }
+ }
+ }
+}
diff --git a/.ci/examples-readme-hydration/package.json b/.ci/examples-readme-hydration/package.json
new file mode 100644
index 00000000..0607ff7b
--- /dev/null
+++ b/.ci/examples-readme-hydration/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "examples-readme-hydration",
+ "version": "0.1.0",
+ "description": "Builds ./examples/README.md based on ./examples/README_TEMPLATE.md",
+ "main": "src/index.js",
+ "scripts": {
+ "start": "node ./index.js"
+ },
+ "keywords": ["cncf", "serverless", "workflow", "specification"],
+ "author": "CNCF Serverless Workflow Specification",
+ "license": "ISC",
+ "dependencies": {
+ "yaml": "^2.3.4"
+ }
+}
diff --git a/.github/workflows/examples-readme-check.yml b/.github/workflows/examples-readme-check.yml
new file mode 100644
index 00000000..da149e4b
--- /dev/null
+++ b/.github/workflows/examples-readme-check.yml
@@ -0,0 +1,21 @@
+name: Check examples README manual updates
+
+on:
+ pull_request:
+ paths:
+ - 'examples/README.md'
+
+jobs:
+ verification:
+ runs-on: ubuntu-latest
+ steps:
+ - if: contains(github.head_ref, 'automation-examples-readme')
+ name: pass
+ run: echo "The update is made by the bot, as expected."
+
+ - if: contains(github.head_ref, 'automation-examples-readme') == false
+ name: fail
+ run: |
+ echo "The file examples/README.md should not be manually edited !"
+ echo "Please update examples/README_TEMPLATE.md instead"
+ exit 1
diff --git a/.github/workflows/examples-readme-hydration.yml b/.github/workflows/examples-readme-hydration.yml
new file mode 100644
index 00000000..e9e2fb47
--- /dev/null
+++ b/.github/workflows/examples-readme-hydration.yml
@@ -0,0 +1,63 @@
+name: Examples README hydration
+
+on:
+ pull_request:
+ types:
+ - closed
+ branches: [ 'main']
+ paths:
+ - 'examples/**/*'
+ - '!examples/README.md'
+
+jobs:
+ build:
+ if: github.repository == 'serverlessworkflow/specification' && github.event.pull_request.merged == true
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ token: ${{ secrets.BOT_PAT }}
+
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 21
+
+ - name: Import GPG key
+ id: import-gpg
+ uses: crazy-max/ghaction-import-gpg@v6
+ with:
+ gpg_private_key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
+ git_config_global: true
+ git_user_signingkey: true
+ git_commit_gpgsign: true
+ git_tag_gpgsign: true
+
+ - run: |
+ set -e
+
+ # Reset origin
+ git remote set-url origin https://${{ secrets.BOT_USERNAME }}:${{ secrets.BOT_PAT }}@github.com/${{ github.repository }}.git
+ git checkout ${{ github.ref_name }}
+
+ # Create a new git branch
+ git checkout -b automation-examples-readme-${{ github.event.pull_request.number }}
+
+ # Install & run JS scripts
+ cd .ci/examples-readme-hydration/
+ npm ci
+ npm start
+
+ # Commit & push changes
+ git config user.name '${{ secrets.BOT_USERNAME }}'
+ git config user.email '${{ secrets.BOT_EMAIL }}'
+ git commit -S -a -m 'Rebuilt examples README.md'
+ git push origin automation-examples-readme-${{ github.event.pull_request.number }}
+
+ # Create a PR on GH
+ gh pr create -B main -H automation-examples-readme-${{ github.event.pull_request.number }} --title '[From CI] Rebuilt examples README' --body 'Automatic hydration of examples README.md'
+ env:
+ GITHUB_TOKEN: ${{ secrets.BOT_PAT }}
diff --git a/examples/README.md b/examples/README.md
index 0bf7f396..1d815d42 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,3 +1,7 @@
+
# Examples
Provides Serverless Workflow language examples
@@ -66,41 +70,40 @@ data output, which is:
```json
{
-"id": "helloworld",
-"version": "1.0.0",
-"specVersion": "0.8",
-"name": "Hello World Workflow",
-"description": "Inject Hello World",
-"start": "Hello State",
-"states":[
- {
- "name":"Hello State",
- "type":"inject",
- "data": {
- "result": "Hello World!"
- },
- "end": true
- }
-]
-}
-```
+ "id": "helloworld",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "Hello World Workflow",
+ "description": "Inject Hello World",
+ "start": "hello-state",
+ "states": [
+ {
+ "name": "hello-state",
+ "type": "inject",
+ "data": {
+ "result": "Hello World!"
+ },
+ "end": true
+ }
+ ]
+}```
```yaml
id: helloworld
-version: '1.0.0'
-specVersion: '0.8'
+version: 1.0.0
+specVersion: "0.8"
name: Hello World Workflow
description: Inject Hello World
-start: Hello State
+start: hello-state
states:
-- name: Hello State
- type: inject
- data:
- result: Hello World!
- end: true
+ - name: hello-state
+ type: inject
+ data:
+ result: Hello World!
+ end: true
```
|
@@ -150,65 +153,68 @@ Which is added to the states data and becomes the workflow data output.
```json
{
-"id": "greeting",
-"version": "1.0.0",
-"specVersion": "0.8",
-"name": "Greeting Workflow",
-"description": "Greet Someone",
-"start": "Greet",
-"functions": [
- {
- "name": "greetingFunction",
- "operation": "file://myapis/greetingapis.json#greeting"
- }
-],
-"states":[
- {
- "name":"Greet",
- "type":"operation",
- "actions":[
- {
- "functionRef": {
- "refName": "greetingFunction",
- "arguments": {
- "name": "${ .person.name }"
- }
- },
- "actionDataFilter": {
- "results": "${ {greeting: .greeting} }"
- }
+ "id": "greeting",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "greeting-workflow",
+ "description": "Greet Someone",
+ "start": "greet",
+ "functions": [
+ {
+ "name": "greeting-function",
+ "type": "openapi",
+ "operation": "file://myapis/greetingapis.json#greeting"
}
- ],
- "end": true
- }
-]
-}
-```
+ ],
+ "states": [
+ {
+ "name": "greet",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "greet-action",
+ "functionRef": {
+ "refName": "greeting-function",
+ "arguments": {
+ "name": "${ .person.name }"
+ }
+ },
+ "actionDataFilter": {
+ "results": "${ {greeting: .greeting} }"
+ }
+ }
+ ],
+ "end": true
+ }
+ ]
+}```
```yaml
id: greeting
-version: '1.0.0'
-specVersion: '0.8'
-name: Greeting Workflow
+version: 1.0.0
+specVersion: "0.8"
+name: greeting-workflow
description: Greet Someone
-start: Greet
+start: greet
functions:
-- name: greetingFunction
- operation: file://myapis/greetingapis.json#greeting
+ - name: greeting-function
+ type: openapi
+ operation: file://myapis/greetingapis.json#greeting
states:
-- name: Greet
- type: operation
- actions:
- - functionRef:
- refName: greetingFunction
- arguments:
- name: "${ .person.name }"
- actionDataFilter:
- results: "${ {greeting: .greeting} }"
- end: true
+ - name: greet
+ type: operation
+ actions:
+ - name: greet-action
+ functionRef:
+ refName: greeting-function
+ arguments:
+ name: ${ .person.name }
+ actionDataFilter:
+ results: "${ {greeting: .greeting} }"
+ end: true
```
|
@@ -295,89 +301,94 @@ filters what is selected to be the state data output which then becomes the work
```json
{
-"id": "eventbasedgreeting",
-"version": "1.0.0",
-"specVersion": "0.8",
-"name": "Event Based Greeting Workflow",
-"description": "Event Based Greeting",
-"start": "Greet",
-"events": [
- {
- "name": "GreetingEvent",
- "type": "greetingEventType",
- "source": "greetingEventSource"
- }
-],
-"functions": [
- {
- "name": "greetingFunction",
- "operation": "file://myapis/greetingapis.json#greeting"
- }
-],
-"states":[
- {
- "name":"Greet",
- "type":"event",
- "onEvents": [{
- "eventRefs": ["GreetingEvent"],
- "eventDataFilter": {
- "data": "${ .greet }",
- "toStateData": "${ .greet }"
- },
- "actions":[
- {
- "functionRef": {
- "refName": "greetingFunction",
- "arguments": {
- "name": "${ .greet.name }"
- }
- }
- }
- ]
- }],
- "stateDataFilter": {
- "output": "${ .payload.greeting }"
- },
- "end": true
- }
-]
-}
-```
+ "id": "eventbasedgreeting",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "Event Based Greeting Workflow",
+ "description": "Event Based Greeting",
+ "start": "greet",
+ "events": [
+ {
+ "name": "greeting-event",
+ "type": "greetingEventType",
+ "source": "greetingEventSource"
+ }
+ ],
+ "functions": [
+ {
+ "name": "greeting-function",
+ "operation": "file://myapis/greetingapis.json#greeting"
+ }
+ ],
+ "states": [
+ {
+ "name": "greet",
+ "type": "event",
+ "onEvents": [
+ {
+ "eventRefs": [
+ "greeting-event"
+ ],
+ "eventDataFilter": {
+ "data": "${ .greet }",
+ "toStateData": "${ .greet }"
+ },
+ "actions": [
+ {
+ "name": "greet-action",
+ "functionRef": {
+ "refName": "greeting-function",
+ "arguments": {
+ "name": "${ .greet.name }"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "stateDataFilter": {
+ "output": "${ .payload.greeting }"
+ },
+ "end": true
+ }
+ ]
+}```
```yaml
id: eventbasedgreeting
-version: '1.0.0'
-specVersion: '0.8'
+version: 1.0.0
+specVersion: "0.8"
name: Event Based Greeting Workflow
description: Event Based Greeting
-start: Greet
+start: greet
events:
-- name: GreetingEvent
- type: greetingEventType
- source: greetingEventSource
+ - name: greeting-event
+ type: greetingEventType
+ source: greetingEventSource
functions:
-- name: greetingFunction
- operation: file://myapis/greetingapis.json#greeting
+ - name: greeting-function
+ operation: file://myapis/greetingapis.json#greeting
states:
-- name: Greet
- type: event
- onEvents:
- - eventRefs:
- - GreetingEvent
- eventDataFilter:
- data: "${ .greet }"
- toStateData: "${ .greet }"
- actions:
- - functionRef:
- refName: greetingFunction
- arguments:
- name: "${ .greet.name }"
- stateDataFilter:
- output: "${ .payload.greeting }"
- end: true
+ - name: greet
+ type: event
+ onEvents:
+ - eventRefs:
+ - greeting-event
+ eventDataFilter:
+ data: ${ .greet }
+ toStateData: ${ .greet }
+ actions:
+ - name: greet-action
+ functionRef:
+ refName: greeting-function
+ arguments:
+ name: ${ .greet.name }
+ stateDataFilter:
+ output: ${ .payload.greeting }
+ end: true
```
|
@@ -423,71 +434,72 @@ result of the workflow execution.
```json
{
-"id": "solvemathproblems",
-"version": "1.0.0",
-"specVersion": "0.8",
-"name": "Solve Math Problems Workflow",
-"description": "Solve math problems",
-"start": "Solve",
-"functions": [
-{
- "name": "solveMathExpressionFunction",
- "operation": "http://myapis.org/mapthapis.json#solveExpression"
-}
-],
-"states":[
-{
- "name":"Solve",
- "type":"foreach",
- "inputCollection": "${ .expressions }",
- "iterationParam": "singleexpression",
- "outputCollection": "${ .results }",
- "actions":[
- {
- "functionRef": {
- "refName": "solveMathExpressionFunction",
- "arguments": {
- "expression": "${ .singleexpression }"
- }
- }
- }
- ],
- "stateDataFilter": {
- "output": "${ .results }"
- },
- "end": true
-}
-]
-}
-```
+ "id": "solvemathproblems",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "solve-math-problems-workflow",
+ "description": "Solve math problems",
+ "start": "solve",
+ "functions": [
+ {
+ "name": "solve-math-exp-func",
+ "operation": "http://myapis.org/mapthapis.json#solveExpression"
+ }
+ ],
+ "states": [
+ {
+ "name": "solve",
+ "type": "foreach",
+ "inputCollection": "${ .expressions }",
+ "iterationParam": "singleexpression",
+ "outputCollection": "${ .results }",
+ "actions": [
+ {
+ "name": "solve-action",
+ "functionRef": {
+ "refName": "solve-math-exp-func",
+ "arguments": {
+ "expression": "${ .singleexpression }"
+ }
+ }
+ }
+ ],
+ "stateDataFilter": {
+ "output": "${ .results }"
+ },
+ "end": true
+ }
+ ]
+}```
```yaml
id: solvemathproblems
-version: '1.0.0'
-specVersion: '0.8'
-name: Solve Math Problems Workflow
+version: 1.0.0
+specVersion: "0.8"
+name: solve-math-problems-workflow
description: Solve math problems
-start: Solve
+start: solve
functions:
-- name: solveMathExpressionFunction
- operation: http://myapis.org/mapthapis.json#solveExpression
+ - name: solve-math-exp-func
+ operation: http://myapis.org/mapthapis.json#solveExpression
states:
-- name: Solve
- type: foreach
- inputCollection: "${ .expressions }"
- iterationParam: singleexpression
- outputCollection: "${ .results }"
- actions:
- - functionRef:
- refName: solveMathExpressionFunction
- arguments:
- expression: "${ .singleexpression }"
- stateDataFilter:
- output: "${ .results }"
- end: true
+ - name: solve
+ type: foreach
+ inputCollection: ${ .expressions }
+ iterationParam: singleexpression
+ outputCollection: ${ .results }
+ actions:
+ - name: solve-action
+ functionRef:
+ refName: solve-math-exp-func
+ arguments:
+ expression: ${ .singleexpression }
+ stateDataFilter:
+ output: ${ .results }
+ end: true
```
|
@@ -520,59 +532,66 @@ to finish execution before it can transition (end workflow execution in this cas
```json
{
-"id": "parallelexec",
-"version": "1.0.0",
-"specVersion": "0.8",
-"name": "Parallel Execution Workflow",
-"description": "Executes two branches in parallel",
-"start": "ParallelExec",
-"states":[
- {
- "name": "ParallelExec",
- "type": "parallel",
- "completionType": "allOf",
- "branches": [
- {
- "name": "ShortDelayBranch",
- "actions": [{
- "subFlowRef": "shortdelayworkflowid"
- }]
- },
+ "id": "parallelexec",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "parallel-execution",
+ "description": "Executes two branches in parallel",
+ "start": "parallelexec",
+ "states": [
{
- "name": "LongDelayBranch",
- "actions": [{
- "subFlowRef": "longdelayworkflowid"
- }]
+ "name": "parallelexec",
+ "type": "parallel",
+ "completionType": "allOf",
+ "branches": [
+ {
+ "name": "short-delay-branch",
+ "actions": [
+ {
+ "name": "short-delay-action",
+ "subFlowRef": "shortdelayworkflowid"
+ }
+ ]
+ },
+ {
+ "name": "long-delay-branch",
+ "actions": [
+ {
+ "name": "short-delay-action",
+ "subFlowRef": "longdelayworkflowid"
+ }
+ ]
+ }
+ ],
+ "end": true
}
- ],
- "end": true
- }
-]
-}
-```
+ ]
+}```
```yaml
id: parallelexec
-version: '1.0.0'
-specVersion: '0.8'
-name: Parallel Execution Workflow
+version: 1.0.0
+specVersion: "0.8"
+name: parallel-execution
description: Executes two branches in parallel
-start: ParallelExec
+start: parallelexec
states:
-- name: ParallelExec
- type: parallel
- completionType: allOf
- branches:
- - name: ShortDelayBranch
- actions:
- - subFlowRef: shortdelayworkflowid
- - name: LongDelayBranch
- actions:
- - subFlowRef: longdelayworkflowid
- end: true
+ - name: parallelexec
+ type: parallel
+ completionType: allOf
+ branches:
+ - name: short-delay-branch
+ actions:
+ - name: short-delay-action
+ subFlowRef: shortdelayworkflowid
+ - name: long-delay-branch
+ actions:
+ - name: short-delay-action
+ subFlowRef: longdelayworkflowid
+ end: true
```
|
@@ -610,62 +629,63 @@ does not wait for its results.
```json
{
- "id": "sendcustomeremail",
- "version": "1.0.0",
- "specVersion": "0.8",
- "name": "Send customer email workflow",
- "description": "Send email to a customer",
- "start": "Send Email",
- "functions": [
- {
- "name": "emailFunction",
- "operation": "file://myapis/emailapis.json#sendEmail"
- }
- ],
- "states":[
- {
- "name":"Send Email",
- "type":"operation",
- "actions":[
- {
- "functionRef": {
- "invoke": "async",
- "refName": "emailFunction",
- "arguments": {
- "customer": "${ .customer }"
- }
- }
- }
- ],
- "end": true
- }
- ]
-}
-```
+ "id": "sendcustomeremail",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "send-customer-email-workflow",
+ "description": "Send email to a customer",
+ "start": "send-email",
+ "functions": [
+ {
+ "name": "email-function",
+ "operation": "file://myapis/emailapis.json#sendEmail"
+ }
+ ],
+ "states": [
+ {
+ "name": "send-email",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "send-email-action",
+ "functionRef": {
+ "invoke": "async",
+ "refName": "email-function",
+ "arguments": {
+ "customer": "${ .customer }"
+ }
+ }
+ }
+ ],
+ "end": true
+ }
+ ]
+}```
```yaml
id: sendcustomeremail
-version: '1.0.0'
-specVersion: '0.8'
-name: Send customer email workflow
+version: 1.0.0
+specVersion: "0.8"
+name: send-customer-email-workflow
description: Send email to a customer
-start: Send Email
+start: send-email
functions:
- - name: emailFunction
- operation: file://myapis/emailapis.json#sendEmail
+ - name: email-function
+ operation: file://myapis/emailapis.json#sendEmail
states:
- - name: Send Email
- type: operation
- actions:
- - functionRef:
- invoke: async
- refName: emailFunction
- arguments:
- customer: "${ .customer }"
- end: true
+ - name: send-email
+ type: operation
+ actions:
+ - name: send-email-action
+ functionRef:
+ invoke: async
+ refName: email-function
+ arguments:
+ customer: ${ .customer }
+ end: true
```
|
@@ -701,52 +721,53 @@ property to `continue`.
```json
{
- "id": "onboardcustomer",
- "version": "1.0.0",
- "specVersion": "0.8",
- "name": "Onboard Customer",
- "description": "Onboard a Customer",
- "start": "Onboard",
- "states":[
- {
- "name":"Onboard",
- "type":"operation",
- "actions":[
- {
- "subFlowRef": {
- "invoke": "async",
- "onParentComplete": "continue",
- "workflowId": "customeronboardingworkflow",
- "version": "1.0"
- }
- }
- ],
- "end": true
- }
- ]
-}
-```
+ "id": "onboardcustomer",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "onboard-customer",
+ "description": "Onboard a Customer",
+ "start": "onboard",
+ "states": [
+ {
+ "name": "onboard",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "onboard-action",
+ "subFlowRef": {
+ "invoke": "async",
+ "onParentComplete": "continue",
+ "workflowId": "customeronboardingworkflow",
+ "version": "1.0.0"
+ }
+ }
+ ],
+ "end": true
+ }
+ ]
+}```
```yaml
id: onboardcustomer
-version: '1.0.0'
-specVersion: '0.8'
-name: Onboard Customer
+version: 1.0.0
+specVersion: "0.8"
+name: onboard-customer
description: Onboard a Customer
-start: Onboard
+start: onboard
states:
- - name: Onboard
- type: operation
- actions:
- - subFlowRef:
- invoke: async
- onParentComplete: continue
- workflowId: customeronboardingworkflow
- version: '1.0.0'
- end: true
+ - name: onboard
+ type: operation
+ actions:
+ - name: onboard-action
+ subFlowRef:
+ invoke: async
+ onParentComplete: continue
+ workflowId: customeronboardingworkflow
+ version: 1.0.0
+ end: true
```
|
@@ -783,123 +804,132 @@ period, the workflow transitions to the "HandleNoVisaDecision" state.
```json
{
-"id": "eventbasedswitchstate",
-"version": "1.0.0",
-"specVersion": "0.8",
-"name": "Event Based Switch Transitions",
-"description": "Event Based Switch Transitions",
-"start": "CheckVisaStatus",
-"events": [
-{
- "name": "visaApprovedEvent",
- "type": "VisaApproved",
- "source": "visaCheckSource"
-},
-{
- "name": "visaRejectedEvent",
- "type": "VisaRejected",
- "source": "visaCheckSource"
-}
-],
-"states":[
- {
- "name":"CheckVisaStatus",
- "type":"switch",
- "eventConditions": [
+ "id": "eventbasedswitchstate",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "event-based-switch-transitions",
+ "description": "Event Based Switch Transitions",
+ "start": "checkvisastatus",
+ "events": [
{
- "eventRef": "visaApprovedEvent",
- "transition": "HandleApprovedVisa"
+ "name": "visa-approved-event",
+ "type": "VisaApproved",
+ "source": "visaCheckSource"
},
{
- "eventRef": "visaRejectedEvent",
- "transition": "HandleRejectedVisa"
+ "name": "visa-rejected-event",
+ "type": "VisaRejected",
+ "source": "visaCheckSource"
}
- ],
- "timeouts": {
- "eventTimeout": "PT1H"
- },
- "defaultCondition": {
- "transition": "HandleNoVisaDecision"
- }
- },
- {
- "name": "HandleApprovedVisa",
- "type": "operation",
- "actions": [
- {
- "subFlowRef": "handleApprovedVisaWorkflowID"
- }
],
- "end": true
- },
- {
- "name": "HandleRejectedVisa",
- "type": "operation",
- "actions": [
+ "states": [
{
- "subFlowRef": "handleRejectedVisaWorkflowID"
- }
- ],
- "end": true
- },
- {
- "name": "HandleNoVisaDecision",
- "type": "operation",
- "actions": [
+ "name": "checkvisastatus",
+ "type": "switch",
+ "eventConditions": [
+ {
+ "eventRef": "visa-approved-event",
+ "transition": "handle-approved-visa",
+ "name": "approved-condition"
+ },
+ {
+ "eventRef": "visa-rejected-event",
+ "transition": "handle-rejected-visa",
+ "name": "rejected-condition"
+ }
+ ],
+ "timeouts": {
+ "eventTimeout": "PT1H"
+ },
+ "defaultCondition": {
+ "transition": "handle-no-visa-decision"
+ }
+ },
{
- "subFlowRef": "handleNoVisaDecisionWorkflowId"
- }
- ],
- "end": true
- }
-]
-}
-```
-
-
-
-
-```yaml
-id: eventbasedswitchstate
-version: '1.0.0'
-specVersion: '0.8'
-name: Event Based Switch Transitions
+ "name": "handle-approved-visa",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "handle-approved-action",
+ "subFlowRef": "handleApprovedVisaWorkflowID"
+ }
+ ],
+ "end": true
+ },
+ {
+ "name": "handle-rejected-visa",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "handle-rejected-action",
+ "subFlowRef": "handleRejectedVisaWorkflowID"
+ }
+ ],
+ "end": true
+ },
+ {
+ "name": "handle-no-visa-decision",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "handle-novisa-action",
+ "subFlowRef": "handleNoVisaDecisionWorkflowId"
+ }
+ ],
+ "end": true
+ }
+ ]
+}```
+
+ |
+
+
+```yaml
+id: eventbasedswitchstate
+version: 1.0.0
+specVersion: "0.8"
+name: event-based-switch-transitions
description: Event Based Switch Transitions
-start: CheckVisaStatus
+start: checkvisastatus
events:
-- name: visaApprovedEvent
- type: VisaApproved
- source: visaCheckSource
-- name: visaRejectedEvent
- type: VisaRejected
- source: visaCheckSource
+ - name: visa-approved-event
+ type: VisaApproved
+ source: visaCheckSource
+ - name: visa-rejected-event
+ type: VisaRejected
+ source: visaCheckSource
states:
-- name: CheckVisaStatus
- type: switch
- eventConditions:
- - eventRef: visaApprovedEvent
- transition: HandleApprovedVisa
- - eventRef: visaRejectedEvent
- transition: HandleRejectedVisa
- timeouts:
- eventTimeout: PT1H
- defaultCondition:
- transition: HandleNoVisaDecision
-- name: HandleApprovedVisa
- type: operation
- actions:
- - subFlowRef: handleApprovedVisaWorkflowID
- end: true
-- name: HandleRejectedVisa
- type: operation
+ - name: checkvisastatus
+ type: switch
+ eventConditions:
+ - eventRef: visa-approved-event
+ transition: handle-approved-visa
+ name: approved-condition
+ - eventRef: visa-rejected-event
+ transition: handle-rejected-visa
+ name: rejected-condition
+ timeouts:
+ eventTimeout: PT1H
+ defaultCondition:
+ transition: handle-no-visa-decision
+ - name: handle-approved-visa
+ type: operation
actions:
- - subFlowRef: handleRejectedVisaWorkflowID
- end: true
-- name: HandleNoVisaDecision
- type: operation
+ - name: handle-approved-action
+ subFlowRef: handleApprovedVisaWorkflowID
+ end: true
+ - name: handle-rejected-visa
+ type: operation
actions:
- - subFlowRef: handleNoVisaDecisionWorkflowId
- end: true
+ - name: handle-rejected-action
+ subFlowRef: handleRejectedVisaWorkflowID
+ end: true
+ - name: handle-no-visa-decision
+ type: operation
+ actions:
+ - name: handle-novisa-action
+ subFlowRef: handleNoVisaDecisionWorkflowId
+ end: true
```
|
@@ -945,103 +975,110 @@ If the applicants age is over 18 we start the application (subflow action). Othe
```json
{
- "id": "applicantrequest",
- "version": "1.0.0",
- "specVersion": "0.8",
- "name": "Applicant Request Decision Workflow",
- "description": "Determine if applicant request is valid",
- "start": "CheckApplication",
- "functions": [
- {
- "name": "sendRejectionEmailFunction",
- "operation": "http://myapis.org/applicationapi.json#emailRejection"
- }
- ],
- "states":[
- {
- "name":"CheckApplication",
- "type":"switch",
- "dataConditions": [
- {
- "condition": "${ .applicants | .age >= 18 }",
- "transition": "StartApplication"
- },
- {
- "condition": "${ .applicants | .age < 18 }",
- "transition": "RejectApplication"
+ "id": "applicantrequest",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "applicant-request-decision-workflow",
+ "description": "Determine if applicant request is valid",
+ "start": "check-application",
+ "functions": [
+ {
+ "name": "send-rejection-email-function",
+ "operation": "http://myapis.org/applicationapi.json#emailRejection"
+ }
+ ],
+ "states": [
+ {
+ "name": "check-application",
+ "type": "switch",
+ "dataConditions": [
+ {
+ "condition": "${ .applicants | .age >= 18 }",
+ "transition": "start-application",
+ "name": "adult-condition"
+ },
+ {
+ "condition": "${ .applicants | .age < 18 }",
+ "transition": "reject-application",
+ "name": "minor-condition"
+ }
+ ],
+ "defaultCondition": {
+ "transition": "reject-application"
}
- ],
- "defaultCondition": {
- "transition": "RejectApplication"
- }
- },
- {
- "name": "StartApplication",
- "type": "operation",
- "actions": [
- {
- "subFlowRef": "startApplicationWorkflowId"
- }
- ],
- "end": true
- },
- {
- "name":"RejectApplication",
- "type":"operation",
- "actionMode":"sequential",
- "actions":[
- {
- "functionRef": {
- "refName": "sendRejectionEmailFunction",
- "arguments": {
- "applicant": "${ .applicant }"
- }
- }
- }
- ],
- "end": true
- }
- ]
-}
-```
+ },
+ {
+ "name": "start-application",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "start-app-action",
+ "subFlowRef": "startApplicationWorkflowId"
+ }
+ ],
+ "end": true
+ },
+ {
+ "name": "reject-application",
+ "type": "operation",
+ "actionMode": "sequential",
+ "actions": [
+ {
+ "name": "send-reject-action",
+ "functionRef": {
+ "refName": "send-rejection-email-function",
+ "arguments": {
+ "applicant": "${ .applicant }"
+ }
+ }
+ }
+ ],
+ "end": true
+ }
+ ]
+}```
```yaml
id: applicantrequest
-version: '1.0.0'
-specVersion: '0.8'
-name: Applicant Request Decision Workflow
+version: 1.0.0
+specVersion: "0.8"
+name: applicant-request-decision-workflow
description: Determine if applicant request is valid
-start: CheckApplication
+start: check-application
functions:
-- name: sendRejectionEmailFunction
- operation: http://myapis.org/applicationapi.json#emailRejection
+ - name: send-rejection-email-function
+ operation: http://myapis.org/applicationapi.json#emailRejection
states:
-- name: CheckApplication
- type: switch
- dataConditions:
- - condition: "${ .applicants | .age >= 18 }"
- transition: StartApplication
- - condition: "${ .applicants | .age < 18 }"
- transition: RejectApplication
- defaultCondition:
- transition: RejectApplication
-- name: StartApplication
- type: operation
- actions:
- - subFlowRef: startApplicationWorkflowId
- end: true
-- name: RejectApplication
- type: operation
- actionMode: sequential
- actions:
- - functionRef:
- refName: sendRejectionEmailFunction
- arguments:
- applicant: "${ .applicant }"
- end: true
+ - name: check-application
+ type: switch
+ dataConditions:
+ - condition: ${ .applicants | .age >= 18 }
+ transition: start-application
+ name: adult-condition
+ - condition: ${ .applicants | .age < 18 }
+ transition: reject-application
+ name: minor-condition
+ defaultCondition:
+ transition: reject-application
+ - name: start-application
+ type: operation
+ actions:
+ - name: start-app-action
+ subFlowRef: startApplicationWorkflowId
+ end: true
+ - name: reject-application
+ type: operation
+ actionMode: sequential
+ actions:
+ - name: send-reject-action
+ functionRef:
+ refName: send-rejection-email-function
+ arguments:
+ applicant: ${ .applicant }
+ end: true
```
|
@@ -1089,163 +1126,172 @@ The data output of the workflow contains the information of the exception caught
```json
{
-"id": "provisionorders",
-"version": "1.0.0",
-"specVersion": "0.8",
-"name": "Provision Orders",
-"description": "Provision Orders and handle errors thrown",
-"start": "ProvisionOrder",
-"functions": [
- {
- "name": "provisionOrderFunction",
- "operation": "http://myapis.org/provisioningapi.json#doProvision"
- }
-],
-"errors": [
- {
- "name": "Missing order id"
- },
- {
- "name": "Missing order item"
- },
- {
- "name": "Missing order quantity"
- }
-],
-"states":[
- {
- "name":"ProvisionOrder",
- "type":"operation",
- "actionMode":"sequential",
- "actions":[
- {
- "functionRef": {
- "refName": "provisionOrderFunction",
- "arguments": {
- "order": "${ .order }"
- }
- }
- }
+ "id": "provisionorders",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "provision-orders",
+ "description": "Provision Orders and handle errors thrown",
+ "start": "provision-order",
+ "functions": [
+ {
+ "name": "provision-order-function",
+ "operation": "http://myapis.org/provisioningapi.json#doProvision"
+ }
],
- "stateDataFilter": {
- "output": "${ .exceptions }"
- },
- "transition": "ApplyOrder",
- "onErrors": [
- {
- "errorRef": "Missing order id",
- "transition": "MissingId"
- },
- {
- "errorRef": "Missing order item",
- "transition": "MissingItem"
- },
- {
- "errorRef": "Missing order quantity",
- "transition": "MissingQuantity"
- }
+ "errors": [
+ {
+ "name": "missing-order-id"
+ },
+ {
+ "name": "missing-order-item"
+ },
+ {
+ "name": "missing-order-quantity"
+ }
+ ],
+ "states": [
+ {
+ "name": "provision-order",
+ "type": "operation",
+ "actionMode": "sequential",
+ "actions": [
+ {
+ "name": "provision-action",
+ "functionRef": {
+ "refName": "provision-order-function",
+ "arguments": {
+ "order": "${ .order }"
+ }
+ }
+ }
+ ],
+ "stateDataFilter": {
+ "output": "${ .exceptions }"
+ },
+ "transition": "apply-order",
+ "onErrors": [
+ {
+ "errorRef": "missing-order-id",
+ "transition": "missing-id"
+ },
+ {
+ "errorRef": "missing-order-item",
+ "transition": "missing-item"
+ },
+ {
+ "errorRef": "missing-order-quantity",
+ "transition": "missing-quantity"
+ }
+ ]
+ },
+ {
+ "name": "missing-id",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "missing-action",
+ "subFlowRef": "handleMissingIdExceptionWorkflow"
+ }
+ ],
+ "end": true
+ },
+ {
+ "name": "missing-item",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "missing-item",
+ "subFlowRef": "handleMissingItemExceptionWorkflow"
+ }
+ ],
+ "end": true
+ },
+ {
+ "name": "missing-quantity",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "missing-quantity",
+ "subFlowRef": "handleMissingQuantityExceptionWorkflow"
+ }
+ ],
+ "end": true
+ },
+ {
+ "name": "apply-order",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "apply-order",
+ "subFlowRef": "applyOrderWorkflowId"
+ }
+ ],
+ "end": true
+ }
]
-},
-{
- "name": "MissingId",
- "type": "operation",
- "actions": [
- {
- "subFlowRef": "handleMissingIdExceptionWorkflow"
- }
- ],
- "end": true
-},
-{
- "name": "MissingItem",
- "type": "operation",
- "actions": [
- {
- "subFlowRef": "handleMissingItemExceptionWorkflow"
- }
- ],
- "end": true
-},
-{
- "name": "MissingQuantity",
- "type": "operation",
- "actions": [
- {
- "subFlowRef": "handleMissingQuantityExceptionWorkflow"
- }
- ],
- "end": true
-},
-{
- "name": "ApplyOrder",
- "type": "operation",
- "actions": [
- {
- "subFlowRef": "applyOrderWorkflowId"
- }
- ],
- "end": true
-}
-]
-}
-```
+}```
```yaml
id: provisionorders
-version: '1.0.0'
-specVersion: '0.8'
-name: Provision Orders
+version: 1.0.0
+specVersion: "0.8"
+name: provision-orders
description: Provision Orders and handle errors thrown
-start: ProvisionOrder
+start: provision-order
functions:
- - name: provisionOrderFunction
- operation: http://myapis.org/provisioningapi.json#doProvision
+ - name: provision-order-function
+ operation: http://myapis.org/provisioningapi.json#doProvision
errors:
- - name: Missing order id
- - name: Missing order item
- - name: Missing order quantity
+ - name: missing-order-id
+ - name: missing-order-item
+ - name: missing-order-quantity
states:
- - name: ProvisionOrder
- type: operation
- actionMode: sequential
- actions:
- - functionRef:
- refName: provisionOrderFunction
- arguments:
- order: "${ .order }"
- stateDataFilter:
- output: "${ .exceptions }"
- transition: ApplyOrder
- onErrors:
- - errorRef: Missing order id
- transition: MissingId
- - errorRef: Missing order item
- transition: MissingItem
- - errorRef: Missing order quantity
- transition: MissingQuantity
- - name: MissingId
- type: operation
- actions:
- - subFlowRef: handleMissingIdExceptionWorkflow
- end: true
- - name: MissingItem
- type: operation
- actions:
- - subFlowRef: handleMissingItemExceptionWorkflow
- end: true
- - name: MissingQuantity
- type: operation
- actions:
- - subFlowRef: handleMissingQuantityExceptionWorkflow
- end: true
- - name: ApplyOrder
- type: operation
- actions:
- - subFlowRef: applyOrderWorkflowId
- end: true
+ - name: provision-order
+ type: operation
+ actionMode: sequential
+ actions:
+ - name: provision-action
+ functionRef:
+ refName: provision-order-function
+ arguments:
+ order: ${ .order }
+ stateDataFilter:
+ output: ${ .exceptions }
+ transition: apply-order
+ onErrors:
+ - errorRef: missing-order-id
+ transition: missing-id
+ - errorRef: missing-order-item
+ transition: missing-item
+ - errorRef: missing-order-quantity
+ transition: missing-quantity
+ - name: missing-id
+ type: operation
+ actions:
+ - name: missing-action
+ subFlowRef: handleMissingIdExceptionWorkflow
+ end: true
+ - name: missing-item
+ type: operation
+ actions:
+ - name: missing-item
+ subFlowRef: handleMissingItemExceptionWorkflow
+ end: true
+ - name: missing-quantity
+ type: operation
+ actions:
+ - name: missing-quantity
+ subFlowRef: handleMissingQuantityExceptionWorkflow
+ end: true
+ - name: apply-order
+ type: operation
+ actions:
+ - name: apply-order
+ subFlowRef: applyOrderWorkflowId
+ end: true
```
|
@@ -1285,211 +1331,222 @@ In the case job submission raises a runtime error, we transition to an Operation
```json
{
- "id": "jobmonitoring",
- "version": "1.0.0",
- "specVersion": "0.8",
- "name": "Job Monitoring",
- "description": "Monitor finished execution of a submitted job",
- "start": "SubmitJob",
- "functions": [
- {
- "name": "submitJob",
- "operation": "http://myapis.org/monitorapi.json#doSubmit"
- },
- {
- "name": "checkJobStatus",
- "operation": "http://myapis.org/monitorapi.json#checkStatus"
- },
- {
- "name": "reportJobSuceeded",
- "operation": "http://myapis.org/monitorapi.json#reportSucceeded"
- },
- {
- "name": "reportJobFailed",
- "operation": "http://myapis.org/monitorapi.json#reportFailure"
- }
- ],
- "states":[
- {
- "name":"SubmitJob",
- "type":"operation",
- "actionMode":"sequential",
- "actions":[
- {
- "functionRef": {
- "refName": "submitJob",
- "arguments": {
- "name": "${ .job.name }"
- }
- },
- "actionDataFilter": {
- "results": "${ .jobuid }"
- }
- }
- ],
- "stateDataFilter": {
- "output": "${ .jobuid }"
- },
- "transition": "WaitForCompletion"
- },
- {
- "name": "WaitForCompletion",
- "type": "sleep",
- "duration": "PT5S",
- "transition": "GetJobStatus"
- },
- {
- "name":"GetJobStatus",
- "type":"operation",
- "actionMode":"sequential",
- "actions":[
- {
- "functionRef": {
- "refName": "checkJobStatus",
- "arguments": {
- "name": "${ .jobuid }"
- }
- },
- "actionDataFilter": {
- "results": "${ .jobstatus }"
- }
- }
- ],
- "stateDataFilter": {
- "output": "${ .jobstatus }"
- },
- "transition": "DetermineCompletion"
- },
- {
- "name":"DetermineCompletion",
- "type":"switch",
- "dataConditions": [
- {
- "condition": "${ .jobStatus == \"SUCCEEDED\" }",
- "transition": "JobSucceeded"
- },
- {
- "condition": "${ .jobStatus == \"FAILED\" }",
- "transition": "JobFailed"
- }
+ "id": "jobmonitoring",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "jobmonitoring",
+ "description": "Monitor finished execution of a submitted job",
+ "start": "submit-job",
+ "functions": [
+ {
+ "name": "submit-job",
+ "operation": "http://myapis.org/monitorapi.json#doSubmit"
+ },
+ {
+ "name": "check-job-status",
+ "operation": "http://myapis.org/monitorapi.json#checkStatus"
+ },
+ {
+ "name": "report-job-suceeded",
+ "operation": "http://myapis.org/monitorapi.json#reportSucceeded"
+ },
+ {
+ "name": "report-job-failed",
+ "operation": "http://myapis.org/monitorapi.json#reportFailure"
+ }
],
- "defaultCondition": {
- "transition": "WaitForCompletion"
- }
- },
- {
- "name":"JobSucceeded",
- "type":"operation",
- "actionMode":"sequential",
- "actions":[
- {
- "functionRef": {
- "refName": "reportJobSuceeded",
- "arguments": {
- "name": "${ .jobuid }"
+ "states": [
+ {
+ "name": "submit-job",
+ "type": "operation",
+ "actionMode": "sequential",
+ "actions": [
+ {
+ "name": "submit-job",
+ "functionRef": {
+ "refName": "submit-job",
+ "arguments": {
+ "name": "${ .job.name }"
+ }
+ },
+ "actionDataFilter": {
+ "results": "${ .jobuid }"
+ }
+ }
+ ],
+ "stateDataFilter": {
+ "output": "${ .jobuid }"
+ },
+ "transition": "wait-for-completion"
+ },
+ {
+ "name": "wait-for-completion",
+ "type": "sleep",
+ "duration": "PT5S",
+ "transition": "get-job-status"
+ },
+ {
+ "name": "get-job-status",
+ "type": "operation",
+ "actionMode": "sequential",
+ "actions": [
+ {
+ "name": "get-job-status",
+ "functionRef": {
+ "refName": "check-job-status",
+ "arguments": {
+ "name": "${ .jobuid }"
+ }
+ },
+ "actionDataFilter": {
+ "results": "${ .jobstatus }"
+ }
+ }
+ ],
+ "stateDataFilter": {
+ "output": "${ .jobstatus }"
+ },
+ "transition": "determine-completion"
+ },
+ {
+ "name": "determine-completion",
+ "type": "switch",
+ "dataConditions": [
+ {
+ "condition": "${ .jobStatus == \"SUCCEEDED\" }",
+ "transition": "job-succeeded",
+ "name": "succeed"
+ },
+ {
+ "condition": "${ .jobStatus == \"FAILED\" }",
+ "transition": "job-failed",
+ "name": "failed"
+ }
+ ],
+ "defaultCondition": {
+ "transition": "wait-for-completion"
}
+ },
+ {
+ "name": "job-succeeded",
+ "type": "operation",
+ "actionMode": "sequential",
+ "actions": [
+ {
+ "name": "job-succeeded",
+ "functionRef": {
+ "refName": "report-job-suceeded",
+ "arguments": {
+ "name": "${ .jobuid }"
+ }
+ }
+ }
+ ],
+ "end": true
+ },
+ {
+ "name": "job-failed",
+ "type": "operation",
+ "actionMode": "sequential",
+ "actions": [
+ {
+ "name": "job-failed",
+ "functionRef": {
+ "refName": "report-job-failed",
+ "arguments": {
+ "name": "${ .jobuid }"
+ }
+ }
+ }
+ ],
+ "end": true
}
- }
- ],
- "end": true
- },
- {
- "name":"JobFailed",
- "type":"operation",
- "actionMode":"sequential",
- "actions":[
- {
- "functionRef": {
- "refName": "reportJobFailed",
- "arguments": {
- "name": "${ .jobuid }"
- }
- }
- }
- ],
- "end": true
- }
- ]
-}
-```
+ ]
+}```
```yaml
id: jobmonitoring
-version: '1.0.0'
-specVersion: '0.8'
-name: Job Monitoring
+version: 1.0.0
+specVersion: "0.8"
+name: jobmonitoring
description: Monitor finished execution of a submitted job
-start: SubmitJob
+start: submit-job
functions:
- - name: submitJob
- operation: http://myapis.org/monitorapi.json#doSubmit
- - name: checkJobStatus
- operation: http://myapis.org/monitorapi.json#checkStatus
- - name: reportJobSuceeded
- operation: http://myapis.org/monitorapi.json#reportSucceeded
- - name: reportJobFailed
- operation: http://myapis.org/monitorapi.json#reportFailure
+ - name: submit-job
+ operation: http://myapis.org/monitorapi.json#doSubmit
+ - name: check-job-status
+ operation: http://myapis.org/monitorapi.json#checkStatus
+ - name: report-job-suceeded
+ operation: http://myapis.org/monitorapi.json#reportSucceeded
+ - name: report-job-failed
+ operation: http://myapis.org/monitorapi.json#reportFailure
states:
- - name: SubmitJob
- type: operation
- actionMode: sequential
- actions:
- - functionRef:
- refName: submitJob
- arguments:
- name: "${ .job.name }"
- actionDataFilter:
- results: "${ .jobuid }"
- stateDataFilter:
- output: "${ .jobuid }"
- transition: WaitForCompletion
- - name: WaitForCompletion
- type: sleep
- duration: PT5S
- transition: GetJobStatus
- - name: GetJobStatus
- type: operation
- actionMode: sequential
- actions:
- - functionRef:
- refName: checkJobStatus
- arguments:
- name: "${ .jobuid }"
- actionDataFilter:
- results: "${ .jobstatus }"
- stateDataFilter:
- output: "${ .jobstatus }"
- transition: DetermineCompletion
- - name: DetermineCompletion
- type: switch
- dataConditions:
- - condition: ${ .jobStatus == "SUCCEEDED" }
- transition: JobSucceeded
- - condition: ${ .jobStatus == "FAILED" }
- transition: JobFailed
- defaultCondition:
- transition: WaitForCompletion
- - name: JobSucceeded
- type: operation
- actionMode: sequential
- actions:
- - functionRef:
- refName: reportJobSuceeded
- arguments:
- name: "${ .jobuid }"
- end: true
- - name: JobFailed
- type: operation
- actionMode: sequential
- actions:
- - functionRef:
- refName: reportJobFailed
- arguments:
- name: "${ .jobuid }"
- end: true
+ - name: submit-job
+ type: operation
+ actionMode: sequential
+ actions:
+ - name: submit-job
+ functionRef:
+ refName: submit-job
+ arguments:
+ name: ${ .job.name }
+ actionDataFilter:
+ results: ${ .jobuid }
+ stateDataFilter:
+ output: ${ .jobuid }
+ transition: wait-for-completion
+ - name: wait-for-completion
+ type: sleep
+ duration: PT5S
+ transition: get-job-status
+ - name: get-job-status
+ type: operation
+ actionMode: sequential
+ actions:
+ - name: get-job-status
+ functionRef:
+ refName: check-job-status
+ arguments:
+ name: ${ .jobuid }
+ actionDataFilter:
+ results: ${ .jobstatus }
+ stateDataFilter:
+ output: ${ .jobstatus }
+ transition: determine-completion
+ - name: determine-completion
+ type: switch
+ dataConditions:
+ - condition: ${ .jobStatus == "SUCCEEDED" }
+ transition: job-succeeded
+ name: succeed
+ - condition: ${ .jobStatus == "FAILED" }
+ transition: job-failed
+ name: failed
+ defaultCondition:
+ transition: wait-for-completion
+ - name: job-succeeded
+ type: operation
+ actionMode: sequential
+ actions:
+ - name: job-succeeded
+ functionRef:
+ refName: report-job-suceeded
+ arguments:
+ name: ${ .jobuid }
+ end: true
+ - name: job-failed
+ type: operation
+ actionMode: sequential
+ actions:
+ - name: job-failed
+ functionRef:
+ refName: report-job-failed
+ arguments:
+ name: ${ .jobuid }
+ end: true
```
|
@@ -1576,83 +1633,86 @@ CloudEvent upon completion of the workflow could look like:
```json
{
-"id": "sendcloudeventonprovision",
-"version": "1.0.0",
-"specVersion": "0.8",
-"name": "Send CloudEvent on provision completion",
-"start": "ProvisionOrdersState",
-"events": [
-{
- "name": "provisioningCompleteEvent",
- "type": "provisionCompleteType",
- "kind": "produced"
-}
-],
-"functions": [
-{
- "name": "provisionOrderFunction",
- "operation": "http://myapis.org/provisioning.json#doProvision"
-}
-],
-"states": [
-{
- "name": "ProvisionOrdersState",
- "type": "foreach",
- "inputCollection": "${ .orders }",
- "iterationParam": "singleorder",
- "outputCollection": "${ .provisionedOrders }",
- "actions": [
- {
- "functionRef": {
- "refName": "provisionOrderFunction",
- "arguments": {
- "order": "${ .singleorder }"
+ "id": "sendcloudeventonprovision",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "sendcloudeventonprovision",
+ "start": "provision-orders-state",
+ "events": [
+ {
+ "name": "provisioning-complete-event",
+ "type": "provisionCompleteType",
+ "kind": "produced"
+ }
+ ],
+ "functions": [
+ {
+ "name": "provision-order-function",
+ "operation": "http://myapis.org/provisioning.json#doProvision"
+ }
+ ],
+ "states": [
+ {
+ "name": "provision-orders-state",
+ "type": "foreach",
+ "inputCollection": "${ .orders }",
+ "iterationParam": "singleorder",
+ "outputCollection": "${ .provisionedOrders }",
+ "actions": [
+ {
+ "name": "provision-order-function",
+ "functionRef": {
+ "refName": "provision-order-function",
+ "arguments": {
+ "order": "${ .singleorder }"
+ }
+ }
}
+ ],
+ "end": {
+ "produceEvents": [
+ {
+ "eventRef": "provisioning-complete-event",
+ "data": "${ .provisionedOrders }"
+ }
+ ]
}
}
- ],
- "end": {
- "produceEvents": [{
- "eventRef": "provisioningCompleteEvent",
- "data": "${ .provisionedOrders }"
- }]
- }
-}
-]
-}
-```
+ ]
+}```
```yaml
id: sendcloudeventonprovision
-version: '1.0.0'
-specVersion: '0.8'
-name: Send CloudEvent on provision completion
-start: ProvisionOrdersState
+version: 1.0.0
+specVersion: "0.8"
+name: sendcloudeventonprovision
+start: provision-orders-state
events:
-- name: provisioningCompleteEvent
- type: provisionCompleteType
- kind: produced
+ - name: provisioning-complete-event
+ type: provisionCompleteType
+ kind: produced
functions:
-- name: provisionOrderFunction
- operation: http://myapis.org/provisioning.json#doProvision
+ - name: provision-order-function
+ operation: http://myapis.org/provisioning.json#doProvision
states:
-- name: ProvisionOrdersState
- type: foreach
- inputCollection: "${ .orders }"
- iterationParam: singleorder
- outputCollection: "${ .provisionedOrders }"
- actions:
- - functionRef:
- refName: provisionOrderFunction
- arguments:
- order: "${ .singleorder }"
- end:
- produceEvents:
- - eventRef: provisioningCompleteEvent
- data: "${ .provisionedOrders }"
+ - name: provision-orders-state
+ type: foreach
+ inputCollection: ${ .orders }
+ iterationParam: singleorder
+ outputCollection: ${ .provisionedOrders }
+ actions:
+ - name: provision-order-function
+ functionRef:
+ refName: provision-order-function
+ arguments:
+ order: ${ .singleorder }
+ end:
+ produceEvents:
+ - eventRef: provisioning-complete-event
+ data: ${ .provisionedOrders }
```
|
@@ -1709,163 +1769,182 @@ have the matching patient id.
```json
{
-"id": "patientVitalsWorkflow",
-"name": "Monitor Patient Vitals",
-"version": "1.0.0",
-"specVersion": "0.8",
-"start": "MonitorVitals",
-"events": [
-{
- "name": "HighBodyTemperature",
- "type": "org.monitor.highBodyTemp",
- "source": "monitoringSource",
- "correlation": [
- {
- "contextAttributeName": "patientId"
- }
- ]
-},
-{
- "name": "HighBloodPressure",
- "type": "org.monitor.highBloodPressure",
- "source": "monitoringSource",
- "correlation": [
- {
- "contextAttributeName": "patientId"
- }
- ]
-},
-{
- "name": "HighRespirationRate",
- "type": "org.monitor.highRespirationRate",
- "source": "monitoringSource",
- "correlation": [
- {
- "contextAttributeName": "patientId"
- }
- ]
-}
-],
-"functions": [
-{
- "name": "callPulmonologist",
- "operation": "http://myapis.org/patientapis.json#callPulmonologist"
-},
-{
- "name": "sendTylenolOrder",
- "operation": "http://myapis.org/patientapis.json#tylenolOrder"
-},
-{
- "name": "callNurse",
- "operation": "http://myapis.org/patientapis.json#callNurse"
-}
-],
-"states": [
-{
-"name": "MonitorVitals",
-"type": "event",
-"exclusive": true,
-"onEvents": [{
- "eventRefs": ["HighBodyTemperature"],
- "actions": [{
- "functionRef": {
- "refName": "sendTylenolOrder",
- "arguments": {
- "patientid": "${ .patientId }"
+ "id": "patientVitalsWorkflow",
+ "name": "patientVitalsWorkflow",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "start": "monitor-vitals",
+ "events": [
+ {
+ "name": "high-body-temperature",
+ "type": "org.monitor.highBodyTemp",
+ "source": "monitoringSource",
+ "correlation": [
+ {
+ "contextAttributeName": "patientId"
}
- }
- }]
- },
- {
- "eventRefs": ["HighBloodPressure"],
- "actions": [{
- "functionRef": {
- "refName": "callNurse",
- "arguments": {
- "patientid": "${ .patientId }"
+ ]
+ },
+ {
+ "name": "high-blood-pressure",
+ "type": "org.monitor.highBloodPressure",
+ "source": "monitoringSource",
+ "correlation": [
+ {
+ "contextAttributeName": "patientId"
}
- }
- }]
- },
- {
- "eventRefs": ["HighRespirationRate"],
- "actions": [{
- "functionRef": {
- "refName": "callPulmonologist",
- "arguments": {
- "patientid": "${ .patientId }"
+ ]
+ },
+ {
+ "name": "high-respiration-rate",
+ "type": "org.monitor.highRespirationRate",
+ "source": "monitoringSource",
+ "correlation": [
+ {
+ "contextAttributeName": "patientId"
+ }
+ ]
+ }
+ ],
+ "functions": [
+ {
+ "name": "call-pulmonologist",
+ "operation": "http://myapis.org/patientapis.json#callPulmonologist"
+ },
+ {
+ "name": "send-tylenol-order",
+ "operation": "http://myapis.org/patientapis.json#tylenolOrder"
+ },
+ {
+ "name": "call-nurse",
+ "operation": "http://myapis.org/patientapis.json#callNurse"
+ }
+ ],
+ "states": [
+ {
+ "name": "monitor-vitals",
+ "type": "event",
+ "exclusive": true,
+ "onEvents": [
+ {
+ "eventRefs": [
+ "high-body-temperature"
+ ],
+ "actions": [
+ {
+ "name": "send-tylenol-order",
+ "functionRef": {
+ "refName": "send-tylenol-order",
+ "arguments": {
+ "patientid": "${ .patientId }"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "eventRefs": [
+ "high-blood-pressure"
+ ],
+ "actions": [
+ {
+ "name": "call-nurse",
+ "functionRef": {
+ "refName": "call-nurse",
+ "arguments": {
+ "patientid": "${ .patientId }"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "eventRefs": [
+ "high-respiration-rate"
+ ],
+ "actions": [
+ {
+ "name": "call-pulmonologist",
+ "functionRef": {
+ "refName": "call-pulmonologist",
+ "arguments": {
+ "patientid": "${ .patientId }"
+ }
+ }
+ }
+ ]
}
+ ],
+ "end": {
+ "terminate": true
}
- }]
- }
-],
-"end": {
- "terminate": true
-}
-}]
-}
-```
+ }
+ ]
+}```
```yaml
id: patientVitalsWorkflow
-name: Monitor Patient Vitals
-version: '1.0.0'
-specVersion: '0.8'
-start: MonitorVitals
+name: patientVitalsWorkflow
+version: 1.0.0
+specVersion: "0.8"
+start: monitor-vitals
events:
-- name: HighBodyTemperature
- type: org.monitor.highBodyTemp
- source: monitoringSource
- correlation:
- - contextAttributeName: patientId
-- name: HighBloodPressure
- type: org.monitor.highBloodPressure
- source: monitoringSource
- correlation:
- - contextAttributeName: patientId
-- name: HighRespirationRate
- type: org.monitor.highRespirationRate
- source: monitoringSource
- correlation:
- - contextAttributeName: patientId
+ - name: high-body-temperature
+ type: org.monitor.highBodyTemp
+ source: monitoringSource
+ correlation:
+ - contextAttributeName: patientId
+ - name: high-blood-pressure
+ type: org.monitor.highBloodPressure
+ source: monitoringSource
+ correlation:
+ - contextAttributeName: patientId
+ - name: high-respiration-rate
+ type: org.monitor.highRespirationRate
+ source: monitoringSource
+ correlation:
+ - contextAttributeName: patientId
functions:
-- name: callPulmonologist
- operation: http://myapis.org/patientapis.json#callPulmonologist
-- name: sendTylenolOrder
- operation: http://myapis.org/patientapis.json#tylenolOrder
-- name: callNurse
- operation: http://myapis.org/patientapis.json#callNurse
+ - name: call-pulmonologist
+ operation: http://myapis.org/patientapis.json#callPulmonologist
+ - name: send-tylenol-order
+ operation: http://myapis.org/patientapis.json#tylenolOrder
+ - name: call-nurse
+ operation: http://myapis.org/patientapis.json#callNurse
states:
-- name: MonitorVitals
- type: event
- exclusive: true
- onEvents:
- - eventRefs:
- - HighBodyTemperature
- actions:
- - functionRef:
- refName: sendTylenolOrder
- arguments:
- patientid: "${ .patientId }"
- - eventRefs:
- - HighBloodPressure
- actions:
- - functionRef:
- refName: callNurse
- arguments:
- patientid: "${ .patientId }"
- - eventRefs:
- - HighRespirationRate
- actions:
- - functionRef:
- refName: callPulmonologist
- arguments:
- patientid: "${ .patientId }"
- end:
- terminate: true
+ - name: monitor-vitals
+ type: event
+ exclusive: true
+ onEvents:
+ - eventRefs:
+ - high-body-temperature
+ actions:
+ - name: send-tylenol-order
+ functionRef:
+ refName: send-tylenol-order
+ arguments:
+ patientid: ${ .patientId }
+ - eventRefs:
+ - high-blood-pressure
+ actions:
+ - name: call-nurse
+ functionRef:
+ refName: call-nurse
+ arguments:
+ patientid: ${ .patientId }
+ - eventRefs:
+ - high-respiration-rate
+ actions:
+ - name: call-pulmonologist
+ functionRef:
+ refName: call-pulmonologist
+ arguments:
+ patientid: ${ .patientId }
+ end:
+ terminate: true
```
|
@@ -1904,125 +1983,126 @@ when all three of these events happened (in no particular order).
```json
{
-"id": "finalizeCollegeApplication",
-"name": "Finalize College Application",
-"version": "1.0.0",
-"specVersion": "0.8",
-"start": "FinalizeApplication",
-"events": [
-{
- "name": "ApplicationSubmitted",
- "type": "org.application.submitted",
- "source": "applicationsource",
- "correlation": [
- {
- "contextAttributeName": "applicantId"
- }
- ]
-},
-{
- "name": "SATScoresReceived",
- "type": "org.application.satscores",
- "source": "applicationsource",
- "correlation": [
- {
- "contextAttributeName": "applicantId"
- }
- ]
-},
-{
- "name": "RecommendationLetterReceived",
- "type": "org.application.recommendationLetter",
- "source": "applicationsource",
- "correlation": [
- {
- "contextAttributeName": "applicantId"
- }
- ]
-}
-],
-"functions": [
-{
- "name": "finalizeApplicationFunction",
- "operation": "http://myapis.org/collegeapplicationapi.json#finalize"
-}
-],
-"states": [
-{
- "name": "FinalizeApplication",
- "type": "event",
- "exclusive": false,
- "onEvents": [
- {
- "eventRefs": [
- "ApplicationSubmitted",
- "SATScoresReceived",
- "RecommendationLetterReceived"
- ],
- "actions": [
- {
- "functionRef": {
- "refName": "finalizeApplicationFunction",
- "arguments": {
- "student": "${ .applicantId }"
- }
- }
+ "id": "finalize-college-application",
+ "name": "finalizeCollegeApplication",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "start": "finalize-application",
+ "events": [
+ {
+ "name": "application-submitted",
+ "type": "org.application.submitted",
+ "source": "applicationsource",
+ "correlation": [
+ {
+ "contextAttributeName": "applicantId"
+ }
+ ]
+ },
+ {
+ "name": "sat-scores-received",
+ "type": "org.application.satscores",
+ "source": "applicationsource",
+ "correlation": [
+ {
+ "contextAttributeName": "applicantId"
+ }
+ ]
+ },
+ {
+ "name": "recommendation-letter-received",
+ "type": "org.application.recommendationLetter",
+ "source": "applicationsource",
+ "correlation": [
+ {
+ "contextAttributeName": "applicantId"
}
]
}
],
- "end": {
- "terminate": true
- }
-}
-]
-}
-```
+ "functions": [
+ {
+ "name": "finalize-application-function",
+ "operation": "http://myapis.org/collegeapplicationapi.json#finalize"
+ }
+ ],
+ "states": [
+ {
+ "name": "finalize-application",
+ "type": "event",
+ "exclusive": false,
+ "onEvents": [
+ {
+ "eventRefs": [
+ "application-submitted",
+ "sat-scores-received",
+ "recommendation-letter-received"
+ ],
+ "actions": [
+ {
+ "name": "finalize-application",
+ "functionRef": {
+ "refName": "finalize-application-function",
+ "arguments": {
+ "student": "${ .applicantId }"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "end": {
+ "terminate": true
+ }
+ }
+ ]
+}```
```yaml
-id: finalizeCollegeApplication
-name: Finalize College Application
-version: '1.0.0'
-specVersion: '0.8'
-start: FinalizeApplication
+id: finalize-college-application
+name: finalizeCollegeApplication
+version: 1.0.0
+specVersion: "0.8"
+start: finalize-application
events:
-- name: ApplicationSubmitted
- type: org.application.submitted
- source: applicationsource
- correlation:
- - contextAttributeName: applicantId
-- name: SATScoresReceived
- type: org.application.satscores
- source: applicationsource
- correlation:
- - contextAttributeName: applicantId
-- name: RecommendationLetterReceived
- type: org.application.recommendationLetter
- source: applicationsource
- correlation:
- - contextAttributeName: applicantId
+ - name: application-submitted
+ type: org.application.submitted
+ source: applicationsource
+ correlation:
+ - contextAttributeName: applicantId
+ - name: sat-scores-received
+ type: org.application.satscores
+ source: applicationsource
+ correlation:
+ - contextAttributeName: applicantId
+ - name: recommendation-letter-received
+ type: org.application.recommendationLetter
+ source: applicationsource
+ correlation:
+ - contextAttributeName: applicantId
functions:
-- name: finalizeApplicationFunction
- operation: http://myapis.org/collegeapplicationapi.json#finalize
+ - name: finalize-application-function
+ operation: http://myapis.org/collegeapplicationapi.json#finalize
states:
-- name: FinalizeApplication
- type: event
- exclusive: false
- onEvents:
- - eventRefs:
- - ApplicationSubmitted
- - SATScoresReceived
- - RecommendationLetterReceived
- actions:
- - functionRef:
- refName: finalizeApplicationFunction
- arguments:
- student: "${ .applicantId }"
- end:
- terminate: true
+ - name: finalize-application
+ type: event
+ exclusive: false
+ onEvents:
+ - eventRefs:
+ - application-submitted
+ - sat-scores-received
+ - recommendation-letter-received
+ actions:
+ - name: finalize-application
+ functionRef:
+ refName: finalize-application-function
+ arguments:
+ student: ${ .applicantId }
+ end:
+ terminate: true
```
|
@@ -2119,84 +2199,89 @@ And for denied credit check, for example:
"id": "customercreditcheck",
"version": "1.0.0",
"specVersion": "0.8",
- "name": "Customer Credit Check Workflow",
+ "name": "customercreditcheck",
"description": "Perform Customer Credit Check",
- "start": "CheckCredit",
+ "start": "check-credit",
"functions": [
{
- "name": "creditCheckFunction",
+ "name": "credit-check-function",
"operation": "http://myapis.org/creditcheckapi.json#doCreditCheck"
},
{
- "name": "sendRejectionEmailFunction",
+ "name": "send-rejection-email-function",
"operation": "http://myapis.org/creditcheckapi.json#rejectionEmail"
}
],
"events": [
{
- "name": "CreditCheckCompletedEvent",
+ "name": "credit-check-completed-event",
"type": "creditCheckCompleteType",
"source": "creditCheckSource",
"correlation": [
- {
- "contextAttributeName": "customerId"
- }
- ]
+ {
+ "contextAttributeName": "customerId"
+ }
+ ]
}
],
"states": [
{
- "name": "CheckCredit",
+ "name": "check-credit",
"type": "callback",
"action": {
+ "name": "check-credit",
"functionRef": {
- "refName": "callCreditCheckMicroservice",
+ "refName": "call-credit-check-microservice",
"arguments": {
"customer": "${ .customer }"
}
}
},
- "eventRef": "CreditCheckCompletedEvent",
+ "eventRef": "credit-check-completed-event",
"timeouts": {
- "stateExecTimeout": "PT15M"
+ "stateExecTimeout": "PT15M"
},
- "transition": "EvaluateDecision"
+ "transition": "evaluate-decision"
},
{
- "name": "EvaluateDecision",
+ "name": "evaluate-decision",
"type": "switch",
"dataConditions": [
{
"condition": "${ .creditCheck | .decision == \"Approved\" }",
- "transition": "StartApplication"
+ "transition": "start-application",
+ "name": "start-application"
},
{
"condition": "${ .creditCheck | .decision == \"Denied\" }",
- "transition": "RejectApplication"
+ "transition": "reject-application",
+ "name": "reject-application"
}
],
"defaultCondition": {
- "transition": "RejectApplication"
+ "transition": "reject-application"
}
},
{
- "name": "StartApplication",
+ "name": "start-application",
"type": "operation",
"actions": [
- {
- "subFlowRef": "startApplicationWorkflowId"
- }
+ {
+ "name": "start-application",
+ "subFlowRef": "startApplicationWorkflowId"
+ }
],
"end": true
},
{
- "name": "RejectApplication",
+ "name": "reject-application",
"type": "operation",
"actionMode": "sequential",
"actions": [
{
+ "name": "reject-application",
"functionRef": {
- "refName": "sendRejectionEmailFunction",
+ "refName": "send-rejection-email-function",
"arguments": {
"applicant": "${ .customer }"
}
@@ -2206,65 +2291,69 @@ And for denied credit check, for example:
"end": true
}
]
-}
-```
+}```
```yaml
id: customercreditcheck
-version: '1.0.0'
-specVersion: '0.8'
-name: Customer Credit Check Workflow
+version: 1.0.0
+specVersion: "0.8"
+name: customercreditcheck
description: Perform Customer Credit Check
-start: CheckCredit
+start: check-credit
functions:
-- name: creditCheckFunction
- operation: http://myapis.org/creditcheckapi.json#doCreditCheck
-- name: sendRejectionEmailFunction
- operation: http://myapis.org/creditcheckapi.json#rejectionEmail
+ - name: credit-check-function
+ operation: http://myapis.org/creditcheckapi.json#doCreditCheck
+ - name: send-rejection-email-function
+ operation: http://myapis.org/creditcheckapi.json#rejectionEmail
events:
-- name: CreditCheckCompletedEvent
- type: creditCheckCompleteType
- source: creditCheckSource
- correlation:
- - contextAttributeName: customerId
+ - name: credit-check-completed-event
+ type: creditCheckCompleteType
+ source: creditCheckSource
+ correlation:
+ - contextAttributeName: customerId
states:
-- name: CheckCredit
- type: callback
- action:
- functionRef:
- refName: callCreditCheckMicroservice
- arguments:
- customer: "${ .customer }"
- eventRef: CreditCheckCompletedEvent
- timeouts:
- stateExecTimeout: PT15M
- transition: EvaluateDecision
-- name: EvaluateDecision
- type: switch
- dataConditions:
- - condition: ${ .creditCheck | .decision == "Approved" }
- transition: StartApplication
- - condition: ${ .creditCheck | .decision == "Denied" }
- transition: RejectApplication
- defaultCondition:
- transition: RejectApplication
-- name: StartApplication
- type: operation
- actions:
- - subFlowRef: startApplicationWorkflowId
- end: true
-- name: RejectApplication
- type: operation
- actionMode: sequential
- actions:
- - functionRef:
- refName: sendRejectionEmailFunction
- arguments:
- applicant: "${ .customer }"
- end: true
+ - name: check-credit
+ type: callback
+ action:
+ name: check-credit
+ functionRef:
+ refName: call-credit-check-microservice
+ arguments:
+ customer: ${ .customer }
+ eventRef: credit-check-completed-event
+ timeouts:
+ stateExecTimeout: PT15M
+ transition: evaluate-decision
+ - name: evaluate-decision
+ type: switch
+ dataConditions:
+ - condition: ${ .creditCheck | .decision == "Approved" }
+ transition: start-application
+ name: start-application
+ - condition: ${ .creditCheck | .decision == "Denied" }
+ transition: reject-application
+ name: reject-application
+ defaultCondition:
+ transition: reject-application
+ - name: start-application
+ type: operation
+ actions:
+ - name: start-application
+ subFlowRef: startApplicationWorkflowId
+ end: true
+ - name: reject-application
+ type: operation
+ actionMode: sequential
+ actions:
+ - name: reject-application
+ functionRef:
+ refName: send-rejection-email-function
+ arguments:
+ applicant: ${ .customer }
+ end: true
```
|
@@ -2321,84 +2410,89 @@ Bidding is done via an online application and bids are received as events are as
```json
{
- "id": "handleCarAuctionBid",
+ "id": "handle-car-auction-bid",
"version": "1.0.0",
"specVersion": "0.8",
- "name": "Car Auction Bidding Workflow",
+ "name": "handle-car-auction-bid",
"description": "Store a single bid whole the car auction is active",
"start": {
- "stateName": "StoreCarAuctionBid",
- "schedule": "R/PT2H"
+ "stateName": "store-car-auction-bid",
+ "schedule": "R/PT2H"
},
"functions": [
{
- "name": "StoreBidFunction",
+ "name": "store-bid-function",
"operation": "http://myapis.org/carauctionapi.json#storeBid"
}
],
"events": [
{
- "name": "CarBidEvent",
+ "name": "car-bid-event",
"type": "carBidMadeType",
"source": "carBidEventSource"
}
],
"states": [
{
- "name": "StoreCarAuctionBid",
- "type": "event",
- "exclusive": true,
- "onEvents": [
- {
- "eventRefs": ["CarBidEvent"],
- "actions": [{
- "functionRef": {
- "refName": "StoreBidFunction",
- "arguments": {
- "bid": "${ .bid }"
+ "name": "store-car-auction-bid",
+ "type": "event",
+ "exclusive": true,
+ "onEvents": [
+ {
+ "eventRefs": [
+ "car-bid-event"
+ ],
+ "actions": [
+ {
+ "name": "car-bid-event",
+ "functionRef": {
+ "refName": "store-bid-function",
+ "arguments": {
+ "bid": "${ .bid }"
+ }
+ }
}
- }
- }]
- }
- ],
- "end": true
+ ]
+ }
+ ],
+ "end": true
}
]
-}
-```
+}```
```yaml
-id: handleCarAuctionBid
-version: '1.0.0'
-specVersion: '0.8'
-name: Car Auction Bidding Workflow
+id: handle-car-auction-bid
+version: 1.0.0
+specVersion: "0.8"
+name: handle-car-auction-bid
description: Store a single bid whole the car auction is active
start:
- stateName: StoreCarAuctionBid
+ stateName: store-car-auction-bid
schedule: R/PT2H
functions:
-- name: StoreBidFunction
- operation: http://myapis.org/carauctionapi.json#storeBid
+ - name: store-bid-function
+ operation: http://myapis.org/carauctionapi.json#storeBid
events:
-- name: CarBidEvent
- type: carBidMadeType
- source: carBidEventSource
+ - name: car-bid-event
+ type: carBidMadeType
+ source: carBidEventSource
states:
-- name: StoreCarAuctionBid
- type: event
- exclusive: true
- onEvents:
- - eventRefs:
- - CarBidEvent
- actions:
- - functionRef:
- refName: StoreBidFunction
- arguments:
- bid: "${ .bid }"
- end: true
+ - name: store-car-auction-bid
+ type: event
+ exclusive: true
+ onEvents:
+ - eventRefs:
+ - car-bid-event
+ actions:
+ - name: car-bid-event
+ functionRef:
+ refName: store-bid-function
+ arguments:
+ bid: ${ .bid }
+ end: true
```
|
@@ -2450,95 +2544,98 @@ The results of the inbox service called is expected to be for example:
```json
{
-"id": "checkInbox",
-"name": "Check Inbox Workflow",
-"version": "1.0.0",
-"specVersion": "0.8",
-"description": "Periodically Check Inbox",
-"start": {
- "stateName": "CheckInbox",
- "schedule": {
- "cron": "0 0/15 * * * ?"
- }
-},
-"functions": [
- {
- "name": "checkInboxFunction",
- "operation": "http://myapis.org/inboxapi.json#checkNewMessages"
- },
- {
- "name": "sendTextFunction",
- "operation": "http://myapis.org/inboxapi.json#sendText"
- }
-],
-"states": [
- {
- "name": "CheckInbox",
- "type": "operation",
- "actionMode": "sequential",
- "actions": [
- {
- "functionRef": "checkInboxFunction"
- }
- ],
- "transition": "SendTextForHighPriority"
+ "id": "check-inbox",
+ "name": "check-inbox",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "description": "Periodically Check Inbox",
+ "start": {
+ "stateName": "check-inbox",
+ "schedule": {
+ "cron": "0 0/15 * * * ?"
+ }
},
- {
- "name": "SendTextForHighPriority",
- "type": "foreach",
- "inputCollection": "${ .messages }",
- "iterationParam": "singlemessage",
- "actions": [
- {
- "functionRef": {
- "refName": "sendTextFunction",
- "arguments": {
- "message": "${ .singlemessage }"
+ "functions": [
+ {
+ "name": "check-inbox-function",
+ "operation": "http://myapis.org/inboxapi.json#checkNewMessages"
+ },
+ {
+ "name": "send-text-function",
+ "operation": "http://myapis.org/inboxapi.json#sendText"
+ }
+ ],
+ "states": [
+ {
+ "name": "check-inbox",
+ "type": "operation",
+ "actionMode": "sequential",
+ "actions": [
+ {
+ "name":"check-inbox",
+ "functionRef": "check-inbox-function"
+ }
+ ],
+ "transition": "send-text-for-high-priority"
+ },
+ {
+ "name": "send-text-for-high-priority",
+ "type": "foreach",
+ "inputCollection": "${ .messages }",
+ "iterationParam": "singlemessage",
+ "actions": [
+ {
+ "name": "send-text-for-high-priority",
+ "functionRef": {
+ "refName": "send-text-function",
+ "arguments": {
+ "message": "${ .singlemessage }"
+ }
}
}
- }
- ],
- "end": true
- }
-]
-}
-```
+ ],
+ "end": true
+ }
+ ]
+}```
```yaml
-id: checkInbox
-name: Check Inbox Workflow
+id: check-inbox
+name: check-inbox
+version: 1.0.0
+specVersion: "0.8"
description: Periodically Check Inbox
-version: '1.0.0'
-specVersion: '0.8'
start:
- stateName: CheckInbox
+ stateName: check-inbox
schedule:
cron: 0 0/15 * * * ?
functions:
-- name: checkInboxFunction
- operation: http://myapis.org/inboxapi.json#checkNewMessages
-- name: sendTextFunction
- operation: http://myapis.org/inboxapi.json#sendText
+ - name: check-inbox-function
+ operation: http://myapis.org/inboxapi.json#checkNewMessages
+ - name: send-text-function
+ operation: http://myapis.org/inboxapi.json#sendText
states:
-- name: CheckInbox
- type: operation
- actionMode: sequential
- actions:
- - functionRef: checkInboxFunction
- transition: SendTextForHighPriority
-- name: SendTextForHighPriority
- type: foreach
- inputCollection: "${ .messages }"
- iterationParam: singlemessage
- actions:
- - functionRef:
- refName: sendTextFunction
- arguments:
- message: "${ .singlemessage }"
- end: true
+ - name: check-inbox
+ type: operation
+ actionMode: sequential
+ actions:
+ - name: check-inbox
+ functionRef: check-inbox-function
+ transition: send-text-for-high-priority
+ - name: send-text-for-high-priority
+ type: foreach
+ inputCollection: ${ .messages }
+ iterationParam: singlemessage
+ actions:
+ - name: send-text-for-high-priority
+ functionRef:
+ refName: send-text-function
+ arguments:
+ message: ${ .singlemessage }
+ end: true
```
|
@@ -2593,21 +2690,21 @@ For this example we assume that the workflow instance is started given the follo
```json
{
- "id": "VetAppointmentWorkflow",
- "name": "Vet Appointment Workflow",
+ "id": "vet-appointment-workflow",
+ "name": "vet-appointment-workflow",
"description": "Vet service call via events",
"version": "1.0.0",
"specVersion": "0.8",
- "start": "MakeVetAppointmentState",
+ "start": "make-vet-appointment-state",
"events": [
{
- "name": "MakeVetAppointment",
+ "name": "make-vet-appointment",
"source": "VetServiceSource",
"type": "events.vet.appointments",
"kind": "produced"
},
{
- "name": "VetAppointmentInfo",
+ "name": "vet-appointment-info",
"source": "VetServiceSource",
"type": "events.vet.appointments",
"kind": "consumed"
@@ -2615,15 +2712,15 @@ For this example we assume that the workflow instance is started given the follo
],
"states": [
{
- "name": "MakeVetAppointmentState",
+ "name": "make-vet-appointment-state",
"type": "operation",
"actions": [
{
- "name": "MakeAppointmentAction",
+ "name": "make-appointment-action",
"eventRef": {
- "produceEventRef": "MakeVetAppointment",
- "data": "${ .patientInfo }",
- "consumeEventRef": "VetAppointmentInfo"
+ "produceEventRef": "make-vet-appointment",
+ "data": "${ .patientInfo }",
+ "consumeEventRef": "vet-appointment-info"
},
"actionDataFilter": {
"results": "${ .appointmentInfo }"
@@ -2631,47 +2728,46 @@ For this example we assume that the workflow instance is started given the follo
}
],
"timeouts": {
- "actionExecTimeout": "PT15M"
+ "actionExecTimeout": "PT15M"
},
"end": true
}
]
-}
-```
+}```
```yaml
-id: VetAppointmentWorkflow
-name: Vet Appointment Workflow
+id: vet-appointment-workflow
+name: vet-appointment-workflow
description: Vet service call via events
-version: '1.0.0'
-specVersion: '0.8'
-start: MakeVetAppointmentState
+version: 1.0.0
+specVersion: "0.8"
+start: make-vet-appointment-state
events:
- - name: MakeVetAppointment
- source: VetServiceSource
- type: events.vet.appointments
- kind: produced
- - name: VetAppointmentInfo
- source: VetServiceSource
- type: events.vet.appointments
- kind: consumed
+ - name: make-vet-appointment
+ source: VetServiceSource
+ type: events.vet.appointments
+ kind: produced
+ - name: vet-appointment-info
+ source: VetServiceSource
+ type: events.vet.appointments
+ kind: consumed
states:
- - name: MakeVetAppointmentState
- type: operation
- actions:
- - name: MakeAppointmentAction
- eventRef:
- produceEventRef: MakeVetAppointment
- data: "${ .patientInfo }"
- consumeEventRef: VetAppointmentInfo
- actionDataFilter:
- results: "${ .appointmentInfo }"
- timeouts:
- actionExecTimeout: PT15M
- end: true
+ - name: make-vet-appointment-state
+ type: operation
+ actions:
+ - name: make-appointment-action
+ eventRef:
+ produceEventRef: make-vet-appointment
+ data: ${ .patientInfo }
+ consumeEventRef: vet-appointment-info
+ actionDataFilter:
+ results: ${ .appointmentInfo }
+ timeouts:
+ actionExecTimeout: PT15M
+ end: true
```
|
@@ -2746,159 +2842,166 @@ In our workflow definition then we can reference these files rather than definin
```json
{
- "id": "paymentconfirmation",
- "version": "1.0.0",
- "specVersion": "0.8",
- "name": "Payment Confirmation Workflow",
- "description": "Performs Payment Confirmation",
- "functions": "functiondefs.json",
- "events": "eventdefs.yml",
- "states": [
- {
- "name": "PaymentReceived",
- "type": "event",
- "onEvents": [
- {
- "eventRefs": [
- "PaymentReceivedEvent"
- ],
- "actions": [
- {
- "name": "checkfunds",
- "functionRef": {
- "refName": "checkFundsAvailability",
- "arguments": {
- "account": "${ .accountId }",
- "paymentamount": "${ .payment.amount }"
+ "id": "paymentconfirmation",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "name": "paymentconfirmation",
+ "description": "Performs Payment Confirmation",
+ "functions": "file://functiondefs.json",
+ "events": "file://eventdefs.yml",
+ "states": [
+ {
+ "name": "payment-received",
+ "type": "event",
+ "onEvents": [
+ {
+ "eventRefs": [
+ "payment-received-event"
+ ],
+ "actions": [
+ {
+ "name": "checkfunds",
+ "functionRef": {
+ "refName": "check-funds-availability",
+ "arguments": {
+ "account": "${ .accountId }",
+ "paymentamount": "${ .payment.amount }"
+ }
+ }
+ }
+ ]
}
- }
- }
- ]
- }
- ],
- "transition": "ConfirmBasedOnFunds"
- },
- {
- "name": "ConfirmBasedOnFunds",
- "type": "switch",
- "dataConditions": [
+ ],
+ "transition": "confirm-based-on-funds"
+ },
{
- "condition": "${ .funds | .available == \"true\" }",
- "transition": "SendPaymentSuccess"
+ "name": "confirm-based-on-funds",
+ "type": "switch",
+ "dataConditions": [
+ {
+ "condition": "${ .funds | .available == \"true\" }",
+ "transition": "send-payment-success",
+ "name": "success"
+ },
+ {
+ "condition": "${ .funds | .available == \"false\" }",
+ "transition": "send-insufficient-results",
+ "name": "failed"
+ }
+ ],
+ "defaultCondition": {
+ "transition": "send-payment-success"
+ }
},
{
- "condition": "${ .funds | .available == \"false\" }",
- "transition": "SendInsufficientResults"
- }
- ],
- "defaultCondition": {
- "transition": "SendPaymentSuccess"
- }
- },
- {
- "name": "SendPaymentSuccess",
- "type": "operation",
- "actions": [
- {
- "functionRef": {
- "refName": "sendSuccessEmail",
- "arguments": {
- "applicant": "${ .customer }"
+ "name": "send-payment-success",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "send-payment-success",
+ "functionRef": {
+ "refName": "send-success-email",
+ "arguments": {
+ "applicant": "${ .customer }"
+ }
+ }
+ }
+ ],
+ "end": {
+ "produceEvents": [
+ {
+ "eventRef": "confirmation-completed-event",
+ "data": "${ .payment }"
+ }
+ ]
}
- }
- }
- ],
- "end": {
- "produceEvents": [
- {
- "eventRef": "ConfirmationCompletedEvent",
- "data": "${ .payment }"
- }
- ]
- }
- },
- {
- "name": "SendInsufficientResults",
- "type": "operation",
- "actions": [
- {
- "functionRef": {
- "refName": "sendInsufficientFundsEmail",
- "arguments": {
- "applicant": "${ .customer }"
+ },
+ {
+ "name": "send-insufficient-results",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "send-insufficient-results",
+ "functionRef": {
+ "refName": "send-insufficient-funds-email",
+ "arguments": {
+ "applicant": "${ .customer }"
+ }
+ }
+ }
+ ],
+ "end": {
+ "produceEvents": [
+ {
+ "eventRef": "confirmation-completed-event",
+ "data": "${ .payment }"
+ }
+ ]
}
- }
}
- ],
- "end": {
- "produceEvents": [
- {
- "eventRef": "ConfirmationCompletedEvent",
- "data": "${ .payment }"
- }
- ]
- }
- }
- ]
-}
-```
+ ]
+}```
```yaml
id: paymentconfirmation
-version: '1.0.0'
-specVersion: '0.8'
-name: Payment Confirmation Workflow
+version: 1.0.0
+specVersion: "0.8"
+name: paymentconfirmation
description: Performs Payment Confirmation
-functions: functiondefs.json
-events: eventdefs.yml
+functions: file://functiondefs.json
+events: file://eventdefs.yml
states:
-- name: PaymentReceived
- type: event
- onEvents:
- - eventRefs:
- - PaymentReceivedEvent
+ - name: payment-received
+ type: event
+ onEvents:
+ - eventRefs:
+ - payment-received-event
+ actions:
+ - name: checkfunds
+ functionRef:
+ refName: check-funds-availability
+ arguments:
+ account: ${ .accountId }
+ paymentamount: ${ .payment.amount }
+ transition: confirm-based-on-funds
+ - name: confirm-based-on-funds
+ type: switch
+ dataConditions:
+ - condition: ${ .funds | .available == "true" }
+ transition: send-payment-success
+ name: success
+ - condition: ${ .funds | .available == "false" }
+ transition: send-insufficient-results
+ name: failed
+ defaultCondition:
+ transition: send-payment-success
+ - name: send-payment-success
+ type: operation
actions:
- - name: checkfunds
- functionRef:
- refName: checkFundsAvailability
- arguments:
- account: "${ .accountId }"
- paymentamount: "${ .payment.amount }"
- transition: ConfirmBasedOnFunds
-- name: ConfirmBasedOnFunds
- type: switch
- dataConditions:
- - condition: "${ .funds | .available == \"true\" }"
- transition: SendPaymentSuccess
- - condition: "${ .funds | .available == \"false\" }"
- transition: SendInsufficientResults
- defaultCondition:
- transition: SendPaymentSuccess
-- name: SendPaymentSuccess
- type: operation
- actions:
- - functionRef:
- refName: sendSuccessEmail
- arguments:
- applicant: "${ .customer }"
- end:
- produceEvents:
- - eventRef: ConfirmationCompletedEvent
- data: "${ .payment }"
-- name: SendInsufficientResults
- type: operation
- actions:
- - functionRef:
- refName: sendInsufficientFundsEmail
- arguments:
- applicant: "${ .customer }"
- end:
- produceEvents:
- - eventRef: ConfirmationCompletedEvent
- data: "${ .payment }"
+ - name: send-payment-success
+ functionRef:
+ refName: send-success-email
+ arguments:
+ applicant: ${ .customer }
+ end:
+ produceEvents:
+ - eventRef: confirmation-completed-event
+ data: ${ .payment }
+ - name: send-insufficient-results
+ type: operation
+ actions:
+ - name: send-insufficient-results
+ functionRef:
+ refName: send-insufficient-funds-email
+ arguments:
+ applicant: ${ .customer }
+ end:
+ produceEvents:
+ - eventRef: confirmation-completed-event
+ data: ${ .payment }
```
|
@@ -2949,135 +3052,146 @@ If the retries are not successful, we want to just gracefully end workflow execu
```json
{
- "id": "patientonboarding",
- "name": "Patient Onboarding Workflow",
- "version": "1.0.0",
- "specVersion": "0.8",
- "start": "Onboard",
- "states": [
- {
- "name": "Onboard",
- "type": "event",
- "onEvents": [
- {
- "eventRefs": [
- "NewPatientEvent"
- ],
- "actions": [
- {
- "functionRef": "StorePatient",
- "retryRef": "ServicesNotAvailableRetryStrategy",
- "retryableErrors": ["ServiceNotAvailable"]
- },
- {
- "functionRef": "AssignDoctor",
- "retryRef": "ServicesNotAvailableRetryStrategy",
- "retryableErrors": ["ServiceNotAvailable"]
- },
- {
- "functionRef": "ScheduleAppt",
- "retryRef": "ServicesNotAvailableRetryStrategy",
- "retryableErrors": ["ServiceNotAvailable"]
- }
- ]
+ "id": "patientonboarding",
+ "name": "patientonboarding",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "start": "onboard",
+ "states": [
+ {
+ "name": "onboard",
+ "type": "event",
+ "onEvents": [
+ {
+ "eventRefs": [
+ "new-patient-event"
+ ],
+ "actions": [
+ {
+ "name": "store-patient",
+ "functionRef": "store-patient",
+ "retryRef": "services-not-available-retry-strategy",
+ "retryableErrors": [
+ "service-not-available"
+ ]
+ },
+ {
+ "name": "assign-doctor",
+ "functionRef": "assign-doctor",
+ "retryRef": "services-not-available-retry-strategy",
+ "retryableErrors": [
+ "service-not-available"
+ ]
+ },
+ {
+ "name": "schedule-appt",
+ "functionRef": "schedule-appt",
+ "retryRef": "services-not-available-retry-strategy",
+ "retryableErrors": [
+ "service-not-available"
+ ]
+ }
+ ]
+ }
+ ],
+ "onErrors": [
+ {
+ "errorRef": "service-not-available",
+ "end": true
+ }
+ ],
+ "end": true
}
- ],
- "onErrors": [
+ ],
+ "events": [
{
- "errorRef": "ServiceNotAvailable",
- "end": true
+ "name": "store-patient",
+ "type": "new.patients.event",
+ "source": "newpatient/+"
}
- ],
- "end": true
- }
- ],
- "events": [
- {
- "name": "StorePatient",
- "type": "new.patients.event",
- "source": "newpatient/+"
- }
- ],
- "functions": [
- {
- "name": "StoreNewPatientInfo",
- "operation": "api/services.json#addPatient"
- },
- {
- "name": "AssignDoctor",
- "operation": "api/services.json#assignDoctor"
- },
- {
- "name": "ScheduleAppt",
- "operation": "api/services.json#scheduleAppointment"
- }
- ],
- "errors": [
- {
- "name": "ServiceNotAvailable",
- "code": "503"
- }
- ],
- "retries": [
- {
- "name": "ServicesNotAvailableRetryStrategy",
- "delay": "PT3S",
- "maxAttempts": 10
- }
- ]
-}
-```
+ ],
+ "functions": [
+ {
+ "name": "store-new-patient-info",
+ "operation": "api/services.json#addPatient"
+ },
+ {
+ "name": "assign-doctor",
+ "operation": "api/services.json#assignDoctor"
+ },
+ {
+ "name": "schedule-appt",
+ "operation": "api/services.json#scheduleAppointment"
+ }
+ ],
+ "errors": [
+ {
+ "name": "service-not-available",
+ "code": "503"
+ }
+ ],
+ "retries": [
+ {
+ "name": "services-not-available-retry-strategy",
+ "delay": "PT3S",
+ "maxAttempts": 10
+ }
+ ]
+}```
```yaml
id: patientonboarding
-name: Patient Onboarding Workflow
-version: '1.0.0'
-specVersion: '0.8'
-start: Onboard
+name: patientonboarding
+version: 1.0.0
+specVersion: "0.8"
+start: onboard
states:
- - name: Onboard
- type: event
- onEvents:
- - eventRefs:
- - NewPatientEvent
- actions:
- - functionRef: StorePatient
- retryRef: ServicesNotAvailableRetryStrategy
- retryableErrors:
- - ServiceNotAvailable
- - functionRef: AssignDoctor
- retryRef: ServicesNotAvailableRetryStrategy
- retryableErrors:
- - ServiceNotAvailable
- - functionRef: ScheduleAppt
- retryRef: ServicesNotAvailableRetryStrategy
- retryableErrors:
- - ServiceNotAvailable
- onErrors:
- - errorRef: ServiceNotAvailable
- end: true
- end: true
+ - name: onboard
+ type: event
+ onEvents:
+ - eventRefs:
+ - new-patient-event
+ actions:
+ - name: store-patient
+ functionRef: store-patient
+ retryRef: services-not-available-retry-strategy
+ retryableErrors:
+ - service-not-available
+ - name: assign-doctor
+ functionRef: assign-doctor
+ retryRef: services-not-available-retry-strategy
+ retryableErrors:
+ - service-not-available
+ - name: schedule-appt
+ functionRef: schedule-appt
+ retryRef: services-not-available-retry-strategy
+ retryableErrors:
+ - service-not-available
+ onErrors:
+ - errorRef: service-not-available
+ end: true
+ end: true
events:
- - name: StorePatient
- type: new.patients.event
- source: newpatient/+
+ - name: store-patient
+ type: new.patients.event
+ source: newpatient/+
functions:
- - name: StoreNewPatientInfo
- operation: api/services.json#addPatient
- - name: AssignDoctor
- operation: api/services.json#assignDoctor
- - name: ScheduleAppt
- operation: api/services.json#scheduleAppointment
+ - name: store-new-patient-info
+ operation: api/services.json#addPatient
+ - name: assign-doctor
+ operation: api/services.json#assignDoctor
+ - name: schedule-appt
+ operation: api/services.json#scheduleAppointment
errors:
- - name: ServiceNotAvailable
- code: '503'
+ - name: service-not-available
+ code: "503"
retries:
- - name: ServicesNotAvailableRetryStrategy
- delay: PT3S
- maxAttempts: 10
+ - name: services-not-available-retry-strategy
+ delay: PT3S
+ maxAttempts: 10
```
|
@@ -3121,250 +3235,264 @@ This example shows the use of the workflow [execTimeout definition](../specifica
```json
{
- "id": "order",
- "name": "Purchase Order Workflow",
- "version": "1.0.0",
- "specVersion": "0.8",
- "start": "StartNewOrder",
- "timeouts": {
- "workflowExecTimeout": {
- "duration": "PT30D",
- "runBefore": "CancelOrder"
- }
- },
- "states": [
- {
- "name": "StartNewOrder",
- "type": "event",
- "onEvents": [
- {
- "eventRefs": ["OrderCreatedEvent"],
- "actions": [
- {
- "functionRef": {
- "refName": "LogNewOrderCreated"
- }
- }
- ]
+ "id": "order",
+ "name": "order",
+ "description": "Purchase Order Workflow",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "start": "start-new-order",
+ "timeouts": {
+ "workflowExecTimeout": {
+ "duration": "PT30D",
+ "runBefore": "CancelOrder"
}
- ],
- "transition": {
- "nextState": "WaitForOrderConfirmation"
- }
},
- {
- "name": "WaitForOrderConfirmation",
- "type": "event",
- "onEvents": [
+ "states": [
{
- "eventRefs": ["OrderConfirmedEvent"],
- "actions": [
- {
- "functionRef": {
- "refName": "LogOrderConfirmed"
- }
+ "name": "start-new-order",
+ "type": "event",
+ "onEvents": [
+ {
+ "eventRefs": [
+ "order-created-event"
+ ],
+ "actions": [
+ {
+ "name": "log-new-order-created",
+ "functionRef": {
+ "refName": "log-new-order-created"
+ }
+ }
+ ]
+ }
+ ],
+ "transition": {
+ "nextState": "wait-for-order-confirmation"
}
- ]
- }
- ],
- "transition": {
- "nextState": "WaitOrderShipped"
- }
- },
- {
- "name": "WaitOrderShipped",
- "type": "event",
- "onEvents": [
+ },
{
- "eventRefs": ["ShipmentSentEvent"],
- "actions": [
- {
- "functionRef": {
- "refName": "LogOrderShipped"
- }
+ "name": "wait-for-order-confirmation",
+ "type": "event",
+ "onEvents": [
+ {
+ "eventRefs": [
+ "order-confirmed-event"
+ ],
+ "actions": [
+ {
+ "name": "log-order-confirmed",
+ "functionRef": {
+ "refName": "log-order-confirmed"
+ }
+ }
+ ]
+ }
+ ],
+ "transition": {
+ "nextState": "wait-order-shipped"
}
- ]
- }
- ],
- "end": {
- "terminate": true,
- "produceEvents": [
- {
- "eventRef": "OrderFinishedEvent"
- }
- ]
- }
- },
- {
- "name": "CancelOrder",
- "type": "operation",
- "actions": [
+ },
{
- "functionRef": {
- "refName": "CancelOrder"
- }
- }
- ],
- "end": {
- "terminate": true,
- "produceEvents": [
- {
- "eventRef": "OrderCancelledEvent"
- }
- ]
- }
- }
- ],
- "events": [
- {
- "name": "OrderCreatedEvent",
- "type": "my.company.orders",
- "source": "/orders/new",
- "correlation": [
+ "name": "wait-order-shipped",
+ "type": "event",
+ "onEvents": [
+ {
+ "eventRefs": [
+ "shipment-sent-event"
+ ],
+ "actions": [
+ {
+ "name": "log-order-shipped",
+ "functionRef": {
+ "refName": "log-order-shipped"
+ }
+ }
+ ]
+ }
+ ],
+ "end": {
+ "terminate": true,
+ "produceEvents": [
+ {
+ "eventRef": "order-finished-event"
+ }
+ ]
+ }
+ },
{
- "contextAttributeName": "orderid"
+ "name": "cancel-order",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "cancel-order",
+ "functionRef": {
+ "refName": "cancel-order"
+ }
+ }
+ ],
+ "end": {
+ "terminate": true,
+ "produceEvents": [
+ {
+ "eventRef": "order-cancelled-event"
+ }
+ ]
+ }
}
- ]
- },
- {
- "name": "OrderConfirmedEvent",
- "type": "my.company.orders",
- "source": "/orders/confirmed",
- "correlation": [
+ ],
+ "events": [
+ {
+ "name": "order-created-event",
+ "type": "my.company.orders",
+ "source": "/orders/new",
+ "correlation": [
+ {
+ "contextAttributeName": "orderid"
+ }
+ ]
+ },
+ {
+ "name": "order-confirmed-event",
+ "type": "my.company.orders",
+ "source": "/orders/confirmed",
+ "correlation": [
+ {
+ "contextAttributeName": "orderid"
+ }
+ ]
+ },
+ {
+ "name": "shipment-sent-event",
+ "type": "my.company.orders",
+ "source": "/orders/shipped",
+ "correlation": [
+ {
+ "contextAttributeName": "orderid"
+ }
+ ]
+ },
+ {
+ "name": "order-finished-event",
+ "type": "my.company.orders",
+ "kind": "produced"
+ },
{
- "contextAttributeName": "orderid"
+ "name": "order-cancelled-event",
+ "type": "my.company.orders",
+ "kind": "produced"
}
- ]
- },
- {
- "name": "ShipmentSentEvent",
- "type": "my.company.orders",
- "source": "/orders/shipped",
- "correlation": [
+ ],
+ "functions": [
+ {
+ "name": "log-new-order-created",
+ "operation": "http.myorg.io/ordersservices.json#logcreated"
+ },
+ {
+ "name": "log-order-confirmed",
+ "operation": "http.myorg.io/ordersservices.json#logconfirmed"
+ },
{
- "contextAttributeName": "orderid"
+ "name": "log-order-shipped",
+ "operation": "http.myorg.io/ordersservices.json#logshipped"
+ },
+ {
+ "name": "cancel-order",
+ "operation": "http.myorg.io/ordersservices.json#calcelorder"
}
- ]
- },
- {
- "name": "OrderFinishedEvent",
- "type": "my.company.orders",
- "kind": "produced"
- },
- {
- "name": "OrderCancelledEvent",
- "type": "my.company.orders",
- "kind": "produced"
- }
- ],
- "functions": [
- {
- "name": "LogNewOrderCreated",
- "operation": "http.myorg.io/ordersservices.json#logcreated"
- },
- {
- "name": "LogOrderConfirmed",
- "operation": "http.myorg.io/ordersservices.json#logconfirmed"
- },
- {
- "name": "LogOrderShipped",
- "operation": "http.myorg.io/ordersservices.json#logshipped"
- },
- {
- "name": "CancelOrder",
- "operation": "http.myorg.io/ordersservices.json#calcelorder"
- }
- ]
-}
-```
+ ]
+}```
```yaml
id: order
-name: Purchase Order Workflow
-version: '1.0.0'
-specVersion: '0.8'
-start: StartNewOrder
-
+name: order
+description: Purchase Order Workflow
+version: 1.0.0
+specVersion: "0.8"
+start: start-new-order
timeouts:
workflowExecTimeout:
duration: PT30D
runBefore: CancelOrder
states:
-- name: StartNewOrder
- type: event
- onEvents:
- - eventRefs:
- - OrderCreatedEvent
- actions:
- - functionRef:
- refName: LogNewOrderCreated
- transition:
- nextState: WaitForOrderConfirmation
-- name: WaitForOrderConfirmation
- type: event
- onEvents:
- - eventRefs:
- - OrderConfirmedEvent
- actions:
- - functionRef:
- refName: LogOrderConfirmed
- transition:
- nextState: WaitOrderShipped
-- name: WaitOrderShipped
- type: event
- onEvents:
- - eventRefs:
- - ShipmentSentEvent
- actions:
- - functionRef:
- refName: LogOrderShipped
- end:
- terminate: true
- produceEvents:
- - eventRef: OrderFinishedEvent
-- name: CancelOrder
- type: operation
- actions:
- - functionRef:
- refName: CancelOrder
- end:
- terminate: true
- produceEvents:
- - eventRef: OrderCancelledEvent
+ - name: start-new-order
+ type: event
+ onEvents:
+ - eventRefs:
+ - order-created-event
+ actions:
+ - name: log-new-order-created
+ functionRef:
+ refName: log-new-order-created
+ transition:
+ nextState: wait-for-order-confirmation
+ - name: wait-for-order-confirmation
+ type: event
+ onEvents:
+ - eventRefs:
+ - order-confirmed-event
+ actions:
+ - name: log-order-confirmed
+ functionRef:
+ refName: log-order-confirmed
+ transition:
+ nextState: wait-order-shipped
+ - name: wait-order-shipped
+ type: event
+ onEvents:
+ - eventRefs:
+ - shipment-sent-event
+ actions:
+ - name: log-order-shipped
+ functionRef:
+ refName: log-order-shipped
+ end:
+ terminate: true
+ produceEvents:
+ - eventRef: order-finished-event
+ - name: cancel-order
+ type: operation
+ actions:
+ - name: cancel-order
+ functionRef:
+ refName: cancel-order
+ end:
+ terminate: true
+ produceEvents:
+ - eventRef: order-cancelled-event
events:
-- name: OrderCreatedEvent
- type: my.company.orders
- source: "/orders/new"
- correlation:
- - contextAttributeName: orderid
-- name: OrderConfirmedEvent
- type: my.company.orders
- source: "/orders/confirmed"
- correlation:
- - contextAttributeName: orderid
-- name: ShipmentSentEvent
- type: my.company.orders
- source: "/orders/shipped"
- correlation:
- - contextAttributeName: orderid
-- name: OrderFinishedEvent
- type: my.company.orders
- kind: produced
-- name: OrderCancelledEvent
- type: my.company.orders
- kind: produced
+ - name: order-created-event
+ type: my.company.orders
+ source: /orders/new
+ correlation:
+ - contextAttributeName: orderid
+ - name: order-confirmed-event
+ type: my.company.orders
+ source: /orders/confirmed
+ correlation:
+ - contextAttributeName: orderid
+ - name: shipment-sent-event
+ type: my.company.orders
+ source: /orders/shipped
+ correlation:
+ - contextAttributeName: orderid
+ - name: order-finished-event
+ type: my.company.orders
+ kind: produced
+ - name: order-cancelled-event
+ type: my.company.orders
+ kind: produced
functions:
-- name: LogNewOrderCreated
- operation: http.myorg.io/ordersservices.json#logcreated
-- name: LogOrderConfirmed
- operation: http.myorg.io/ordersservices.json#logconfirmed
-- name: LogOrderShipped
- operation: http.myorg.io/ordersservices.json#logshipped
-- name: CancelOrder
- operation: http.myorg.io/ordersservices.json#calcelorder
+ - name: log-new-order-created
+ operation: http.myorg.io/ordersservices.json#logcreated
+ - name: log-order-confirmed
+ operation: http.myorg.io/ordersservices.json#logconfirmed
+ - name: log-order-shipped
+ operation: http.myorg.io/ordersservices.json#logshipped
+ - name: cancel-order
+ operation: http.myorg.io/ordersservices.json#calcelorder
```
|
@@ -3405,144 +3533,152 @@ the data for an hour, send report, and so on.
```json
{
- "id": "roomreadings",
- "name": "Room Temp and Humidity Workflow",
- "version": "1.0.0",
- "specVersion": "0.8",
- "start": "ConsumeReading",
- "timeouts": {
- "workflowExecTimeout": {
- "duration": "PT1H",
- "runBefore": "GenerateReport"
- }
- },
- "keepActive": true,
- "states": [
- {
- "name": "ConsumeReading",
- "type": "event",
- "onEvents": [
- {
- "eventRefs": ["TemperatureEvent", "HumidityEvent"],
- "actions": [
- {
- "functionRef": {
- "refName": "LogReading"
- }
- }
- ],
- "eventDataFilter": {
- "toStateData": "${ .readings }"
- }
+ "id": "roomreadings",
+ "name": "roomreadings",
+ "description": "Room Temp and Humidity Workflow",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "start": "consume-reading",
+ "timeouts": {
+ "workflowExecTimeout": {
+ "duration": "PT1H",
+ "runBefore": "generate-report"
}
- ],
- "end": true
},
- {
- "name": "GenerateReport",
- "type": "operation",
- "actions": [
- {
- "functionRef": {
- "refName": "ProduceReport",
- "arguments": {
- "data": "${ .readings }"
+ "keepActive": true,
+ "states": [
+ {
+ "name": "consume-reading",
+ "type": "event",
+ "onEvents": [
+ {
+ "eventRefs": [
+ "temperature-event",
+ "humidity-event"
+ ],
+ "actions": [
+ {
+ "name": "log-reading",
+ "functionRef": {
+ "refName": "log-reading"
+ }
+ }
+ ],
+ "eventDataFilter": {
+ "toStateData": "${ .readings }"
+ }
+ }
+ ],
+ "end": true
+ },
+ {
+ "name": "generate-report",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "generate-report",
+ "functionRef": {
+ "refName": "produce-report",
+ "arguments": {
+ "data": "${ .readings }"
+ }
+ }
+ }
+ ],
+ "end": {
+ "terminate": true
}
- }
}
- ],
- "end": {
- "terminate": true
- }
- }
- ],
- "events": [
- {
- "name": "TemperatureEvent",
- "type": "my.home.sensors",
- "source": "/home/rooms/+",
- "correlation": [
+ ],
+ "events": [
+ {
+ "name": "temperature-event",
+ "type": "my.home.sensors",
+ "source": "/home/rooms/+",
+ "correlation": [
+ {
+ "contextAttributeName": "roomId"
+ }
+ ]
+ },
{
- "contextAttributeName": "roomId"
+ "name": "humidity-event",
+ "type": "my.home.sensors",
+ "source": "/home/rooms/+",
+ "correlation": [
+ {
+ "contextAttributeName": "roomId"
+ }
+ ]
}
- ]
- },
- {
- "name": "HumidityEvent",
- "type": "my.home.sensors",
- "source": "/home/rooms/+",
- "correlation": [
+ ],
+ "functions": [
+ {
+ "name": "log-reading",
+ "operation": "http.myorg.io/ordersservices.json#logreading"
+ },
{
- "contextAttributeName": "roomId"
+ "name": "produce-report",
+ "operation": "http.myorg.io/ordersservices.json#produceReport"
}
- ]
- }
- ],
- "functions": [
- {
- "name": "LogReading",
- "operation": "http.myorg.io/ordersservices.json#logreading"
- },
- {
- "name": "ProduceReport",
- "operation": "http.myorg.io/ordersservices.json#produceReport"
- }
- ]
-}
-```
+ ]
+}```
```yaml
id: roomreadings
-name: Room Temp and Humidity Workflow
-version: '1.0.0'
-specVersion: '0.8'
-start: ConsumeReading
+name: roomreadings
+description: Room Temp and Humidity Workflow
+version: 1.0.0
+specVersion: "0.8"
+start: consume-reading
timeouts:
workflowExecTimeout:
duration: PT1H
- runBefore: GenerateReport
+ runBefore: generate-report
keepActive: true
states:
-- name: ConsumeReading
- type: event
- onEvents:
- - eventRefs:
- - TemperatureEvent
- - HumidityEvent
+ - name: consume-reading
+ type: event
+ onEvents:
+ - eventRefs:
+ - temperature-event
+ - humidity-event
+ actions:
+ - name: log-reading
+ functionRef:
+ refName: log-reading
+ eventDataFilter:
+ toStateData: ${ .readings }
+ end: true
+ - name: generate-report
+ type: operation
actions:
- - functionRef:
- refName: LogReading
- eventDataFilter:
- toStateData: "${ .readings }"
- end: true
-- name: GenerateReport
- type: operation
- actions:
- - functionRef:
- refName: ProduceReport
- arguments:
- data: "${ .readings }"
- end:
- terminate: true
+ - name: generate-report
+ functionRef:
+ refName: produce-report
+ arguments:
+ data: ${ .readings }
+ end:
+ terminate: true
events:
-- name: TemperatureEvent
- type: my.home.sensors
- source: "/home/rooms/+"
- correlation:
- - contextAttributeName: roomId
-- name: HumidityEvent
- type: my.home.sensors
- source: "/home/rooms/+"
- correlation:
- - contextAttributeName: roomId
+ - name: temperature-event
+ type: my.home.sensors
+ source: /home/rooms/+
+ correlation:
+ - contextAttributeName: roomId
+ - name: humidity-event
+ type: my.home.sensors
+ source: /home/rooms/+
+ correlation:
+ - contextAttributeName: roomId
functions:
-- name: LogReading
- operation: http.myorg.io/ordersservices.json#logreading
-- name: ProduceReport
- operation: http.myorg.io/ordersservices.json#produceReport
+ - name: log-reading
+ operation: http.myorg.io/ordersservices.json#logreading
+ - name: produce-report
+ operation: http.myorg.io/ordersservices.json#produceReport
```
|
@@ -3579,103 +3715,108 @@ We fist define our top-level workflow for this example:
```json
{
- "id": "checkcarvitals",
- "name": "Check Car Vitals Workflow",
- "version": "1.0.0",
- "specVersion": "0.8",
- "start": "WhenCarIsOn",
- "states": [
- {
- "name": "WhenCarIsOn",
- "type": "event",
- "onEvents": [
- {
- "eventRefs": ["CarTurnedOnEvent"]
- }
- ],
- "transition": "DoCarVitalChecks"
- },
- {
- "name": "DoCarVitalChecks",
- "type": "operation",
- "actions": [
- {
- "subFlowRef": "vitalscheck",
- "sleep": {
- "after": "PT1S"
- }
- }
- ],
- "transition": "CheckContinueVitalChecks"
- },
- {
- "name": "CheckContinueVitalChecks",
- "type": "switch",
- "eventConditions": [
- {
- "name": "Car Turned Off Condition",
- "eventRef": "CarTurnedOffEvent",
- "end": true
- }
- ],
- "defaultCondition": {
- "transition": "DoCarVitalChecks"
- }
- }
- ],
- "events": [
- {
- "name": "CarTurnedOnEvent",
- "type": "car.events",
- "source": "my/car"
- },
- {
- "name": "CarTurnedOffEvent",
- "type": "car.events",
- "source": "my/car"
- }
- ]
-}
-```
+ "id": "checkcarvitals",
+ "name": "checkcarvitals",
+ "description": "Check Car Vitals Workflow",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "start": "when-car-is-on",
+ "states": [
+ {
+ "name": "when-car-is-on",
+ "type": "event",
+ "onEvents": [
+ {
+ "eventRefs": [
+ "car-turned-on-event"
+ ]
+ }
+ ],
+ "transition": "do-car-vital-checks"
+ },
+ {
+ "name": "do-car-vital-checks",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "do-car-vital-checks",
+ "subFlowRef": "vitalscheck",
+ "sleep": {
+ "after": "PT1S"
+ }
+ }
+ ],
+ "transition": "check-continue-vital-checks"
+ },
+ {
+ "name": "check-continue-vital-checks",
+ "type": "switch",
+ "eventConditions": [
+ {
+ "name": "car-turned-off-condition",
+ "eventRef": "car-turned-off-event",
+ "end": true
+ }
+ ],
+ "defaultCondition": {
+ "transition": "do-car-vital-checks"
+ }
+ }
+ ],
+ "events": [
+ {
+ "name": "car-turned-on-event",
+ "type": "car.events",
+ "source": "my/car"
+ },
+ {
+ "name": "car-turned-off-event",
+ "type": "car.events",
+ "source": "my/car"
+ }
+ ]
+}```
```yaml
id: checkcarvitals
-name: Check Car Vitals Workflow
-version: '1.0.0'
-specVersion: '0.8'
-start: WhenCarIsOn
+name: checkcarvitals
+description: Check Car Vitals Workflow
+version: 1.0.0
+specVersion: "0.8"
+start: when-car-is-on
states:
- - name: WhenCarIsOn
- type: event
- onEvents:
- - eventRefs:
- - CarTurnedOnEvent
- transition: DoCarVitalChecks
- - name: DoCarVitalChecks
- type: operation
- actions:
- - subFlowRef: vitalscheck
- sleep:
- after: PT1S
- transition: CheckContinueVitalChecks
- - name: CheckContinueVitalChecks
- type: switch
- eventConditions:
- - name: Car Turned Off Condition
- eventRef: CarTurnedOffEvent
- end: true
- defaultCondition:
- transition: DoCarVitalChecks
+ - name: when-car-is-on
+ type: event
+ onEvents:
+ - eventRefs:
+ - car-turned-on-event
+ transition: do-car-vital-checks
+ - name: do-car-vital-checks
+ type: operation
+ actions:
+ - name: do-car-vital-checks
+ subFlowRef: vitalscheck
+ sleep:
+ after: PT1S
+ transition: check-continue-vital-checks
+ - name: check-continue-vital-checks
+ type: switch
+ eventConditions:
+ - name: car-turned-off-condition
+ eventRef: car-turned-off-event
+ end: true
+ defaultCondition:
+ transition: do-car-vital-checks
events:
- - name: CarTurnedOnEvent
- type: car.events
- source: my/car
- - name: CarTurnedOffEvent
- type: car.events
- source: my/car
+ - name: car-turned-on-event
+ type: car.events
+ source: my/car
+ - name: car-turned-off-event
+ type: car.events
+ source: my/car
```
|
@@ -3694,59 +3835,99 @@ And then our reusable sub-workflow which performs the checking of our car vitals
```json
{
- "id": "vitalscheck",
- "name": "Car Vitals Check",
- "version": "1.0.0",
- "specVersion": "0.8",
- "start": "CheckVitals",
- "states": [
- {
- "name": "CheckVitals",
- "type": "operation",
- "actions": [
- {
- "functionRef": "Check Tire Pressure"
- },
- {
- "functionRef": "Check Oil Pressure"
- },
- {
- "functionRef": "Check Coolant Level"
- },
- {
- "functionRef": "Check Battery"
- }
- ],
- "end": {
- "produceEvents": [
- {
- "eventRef": "DisplayChecksOnDashboard",
- "data": "${ .evaluations }"
- }
+ "id": "vitalscheck",
+ "name": "vitalscheck",
+ "description": "Car Vitals Check",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "start": "check-vitals",
+ "states": [
+ {
+ "name": "check-vitals",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "check-tire-pressure",
+ "functionRef": "check-tire-pressure"
+ },
+ {
+ "name": "check-oil-pressure",
+ "functionRef": "check-oil-pressure"
+ },
+ {
+ "name": "check-coolant-level",
+ "functionRef": "check-coolant-level"
+ },
+ {
+ "name": "check-battery",
+ "functionRef": "check-battery"
+ }
+ ],
+ "end": {
+ "produceEvents": [
+ {
+ "eventRef": "display-checks-on-dashboard",
+ "data": "${ .evaluations }"
+ }
+ ]
+ }
+ }
+ ],
+ "functions": [
+ {
+ "name": "check-tire-pressure",
+ "operation": "mycarservices.json#checktirepressure"
+ },
+ {
+ "name": "check-oil-pressure",
+ "operation": "mycarservices.json#checkoilpressure"
+ },
+ {
+ "name": "check-coolant-level",
+ "operation": "mycarservices.json#checkcoolantlevel"
+ },
+ {
+ "name": "check-battery",
+ "operation": "mycarservices.json#checkbattery"
+ }
]
+}```
- }
- }
- ],
- "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"
- }
- ]
-}
+
+
+
+```yaml
+id: vitalscheck
+name: vitalscheck
+description: Car Vitals Check
+version: 1.0.0
+specVersion: "0.8"
+start: check-vitals
+states:
+ - name: check-vitals
+ type: operation
+ actions:
+ - name: check-tire-pressure
+ functionRef: check-tire-pressure
+ - name: check-oil-pressure
+ functionRef: check-oil-pressure
+ - name: check-coolant-level
+ functionRef: check-coolant-level
+ - name: check-battery
+ functionRef: check-battery
+ end:
+ produceEvents:
+ - eventRef: display-checks-on-dashboard
+ data: ${ .evaluations }
+functions:
+ - name: check-tire-pressure
+ operation: mycarservices.json#checktirepressure
+ - name: check-oil-pressure
+ operation: mycarservices.json#checkoilpressure
+ - name: check-coolant-level
+ operation: mycarservices.json#checkcoolantlevel
+ - name: check-battery
+ operation: mycarservices.json#checkbattery
```
|
@@ -3834,249 +4015,264 @@ For the sake of the example we assume the functions and event definitions are de
```json
{
- "id": "booklending",
- "name": "Book Lending Workflow",
- "version": "1.0.0",
- "specVersion": "0.8",
- "start": "Book Lending Request",
- "states": [
- {
- "name": "Book Lending Request",
- "type": "event",
- "onEvents": [
- {
- "eventRefs": ["Book Lending Request Event"]
- }
- ],
- "transition": "Get Book Status"
- },
- {
- "name": "Get Book Status",
- "type": "operation",
- "actions": [
- {
- "functionRef": {
- "refName": "Get status for book",
- "arguments": {
- "bookid": "${ .book.id }"
- }
- }
- }
- ],
- "transition": "Book Status Decision"
- },
- {
- "name": "Book Status Decision",
- "type": "switch",
- "dataConditions": [
- {
- "name": "Book is on loan",
- "condition": "${ .book.status == \"onloan\" }",
- "transition": "Report Status To Lender"
- },
- {
- "name": "Check is available",
- "condition": "${ .book.status == \"available\" }",
- "transition": "Check Out Book"
- }
- ],
- "defaultCondition": {
- "end": true
- }
- },
- {
- "name": "Report Status To Lender",
- "type": "operation",
- "actions": [
- {
- "functionRef": {
- "refName": "Send status to lender",
- "arguments": {
- "bookid": "${ .book.id }",
- "message": "Book ${ .book.title } is already on loan"
- }
- }
- }
- ],
- "transition": "Wait for Lender response"
- },
- {
- "name": "Wait for Lender response",
- "type": "switch",
- "eventConditions": [
- {
- "name": "Hold Book",
- "eventRef": "Hold Book Event",
- "transition": "Request Hold"
- },
- {
- "name": "Decline Book Hold",
- "eventRef": "Decline Hold Event",
- "transition": "Cancel Request"
- }
- ],
- "defaultCondition": {
- "end": true
- }
- },
- {
- "name": "Request Hold",
- "type": "operation",
- "actions": [
- {
- "functionRef": {
- "refName": "Request hold for lender",
- "arguments": {
- "bookid": "${ .book.id }",
- "lender": "${ .lender }"
- }
- }
- }
- ],
- "transition": "Sleep two weeks"
- },
- {
- "name": "Cancel Request",
- "type": "operation",
- "actions": [
- {
- "functionRef": {
- "refName": "Cancel hold request for lender",
- "arguments": {
- "bookid": "${ .book.id }",
- "lender": "${ .lender }"
- }
- }
- }
- ],
- "transition": "Sleep two weeks"
- },
- {
- "name": "Sleep two weeks",
- "type": "sleep",
- "duration": "PT2W",
- "transition": "Get Book Status"
- },
- {
- "name": "Check Out Book",
- "type": "operation",
- "actions": [
- {
- "functionRef": {
- "refName": "Check out book with id",
- "arguments": {
- "bookid": "${ .book.id }"
- }
- }
- },
- {
- "functionRef": {
- "refName": "Notify Lender for checkout",
- "arguments": {
- "bookid": "${ .book.id }",
- "lender": "${ .lender }"
- }
- }
- }
- ],
- "end": true
- }
- ],
- "functions": "file://books/lending/functions.json",
- "events": "file://books/lending/events.json"
-}
-```
+ "id": "booklending",
+ "name": "booklending",
+ "description": "Book Lending Workflow",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "start": "book-lending-request",
+ "states": [
+ {
+ "name": "book-lending-request",
+ "type": "event",
+ "onEvents": [
+ {
+ "eventRefs": [
+ "book-lending-request-event"
+ ]
+ }
+ ],
+ "transition": "get-book-status"
+ },
+ {
+ "name": "get-book-status",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "get-book-status",
+ "functionRef": {
+ "refName": "get-status-for-book",
+ "arguments": {
+ "bookid": "${ .book.id }"
+ }
+ }
+ }
+ ],
+ "transition": "book-status-decision"
+ },
+ {
+ "name": "book-status-decision",
+ "type": "switch",
+ "dataConditions": [
+ {
+ "name": "book-is-on-loan",
+ "condition": "${ .book.status == \"onloan\" }",
+ "transition": "report-status-to-lender"
+ },
+ {
+ "name": "check-is-available",
+ "condition": "${ .book.status == \"available\" }",
+ "transition": "check-out-book"
+ }
+ ],
+ "defaultCondition": {
+ "end": true
+ }
+ },
+ {
+ "name": "report-status-to-lender",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "report-status-to-lender",
+ "functionRef": {
+ "refName": "send-status-to-lender",
+ "arguments": {
+ "bookid": "${ .book.id }",
+ "message": "Book ${ .book.title } is already on loan"
+ }
+ }
+ }
+ ],
+ "transition": "wait-for-lender-response"
+ },
+ {
+ "name": "wait-for-lender-response",
+ "type": "switch",
+ "eventConditions": [
+ {
+ "name": "hold-book",
+ "eventRef": "hold-book-event",
+ "transition": "request-hold"
+ },
+ {
+ "name": "decline-book-hold",
+ "eventRef": "decline-hold-event",
+ "transition": "cancel-request"
+ }
+ ],
+ "defaultCondition": {
+ "end": true
+ }
+ },
+ {
+ "name": "request-hold",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "request-hold",
+ "functionRef": {
+ "refName": "request-hold-for-lender",
+ "arguments": {
+ "bookid": "${ .book.id }",
+ "lender": "${ .lender }"
+ }
+ }
+ }
+ ],
+ "transition": "sleep-two-weeks"
+ },
+ {
+ "name": "cancel-request",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "cancel-request",
+ "functionRef": {
+ "refName": "cancel-hold-request-for-lender",
+ "arguments": {
+ "bookid": "${ .book.id }",
+ "lender": "${ .lender }"
+ }
+ }
+ }
+ ],
+ "transition": "sleep-two-weeks"
+ },
+ {
+ "name": "sleep-two-weeks",
+ "type": "sleep",
+ "duration": "PT2W",
+ "transition": "get-book-status"
+ },
+ {
+ "name": "check-out-book",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "check-out-book",
+ "functionRef": {
+ "refName": "check-out-book-with-id",
+ "arguments": {
+ "bookid": "${ .book.id }"
+ }
+ }
+ },
+ {
+ "name": "notify-lender-for-checkout",
+ "functionRef": {
+ "refName": "notify-lender-for-checkout",
+ "arguments": {
+ "bookid": "${ .book.id }",
+ "lender": "${ .lender }"
+ }
+ }
+ }
+ ],
+ "end": true
+ }
+ ],
+ "functions": "file://books/lending/functions.json",
+ "events": "file://books/lending/events.json"
+}```
```yaml
id: booklending
-name: Book Lending Workflow
-version: '1.0.0'
-specVersion: '0.8'
-start: Book Lending Request
+name: booklending
+description: Book Lending Workflow
+version: 1.0.0
+specVersion: "0.8"
+start: book-lending-request
states:
- - name: Book Lending Request
- type: event
- onEvents:
- - eventRefs:
- - Book Lending Request Event
- transition: Get Book Status
- - name: Get Book Status
- type: operation
- actions:
- - functionRef:
- refName: Get status for book
- arguments:
- bookid: "${ .book.id }"
- transition: Book Status Decision
- - name: Book Status Decision
- type: switch
- dataConditions:
- - name: Book is on loan
- condition: ${ .book.status == "onloan" }
- transition: Report Status To Lender
- - name: Check is available
- condition: ${ .book.status == "available" }
- transition: Check Out Book
- defaultCondition:
- end: true
- - name: Report Status To Lender
- type: operation
- actions:
- - functionRef:
- refName: Send status to lender
- arguments:
- bookid: "${ .book.id }"
- message: Book ${ .book.title } is already on loan
- transition: Wait for Lender response
- - name: Wait for Lender response
- type: switch
- eventConditions:
- - name: Hold Book
- eventRef: Hold Book Event
- transition: Request Hold
- - name: Decline Book Hold
- eventRef: Decline Hold Event
- transition: Cancel Request
- defaultCondition:
+ - name: book-lending-request
+ type: event
+ onEvents:
+ - eventRefs:
+ - book-lending-request-event
+ transition: get-book-status
+ - name: get-book-status
+ type: operation
+ actions:
+ - name: get-book-status
+ functionRef:
+ refName: get-status-for-book
+ arguments:
+ bookid: ${ .book.id }
+ transition: book-status-decision
+ - name: book-status-decision
+ type: switch
+ dataConditions:
+ - name: book-is-on-loan
+ condition: ${ .book.status == "onloan" }
+ transition: report-status-to-lender
+ - name: check-is-available
+ condition: ${ .book.status == "available" }
+ transition: check-out-book
+ defaultCondition:
+ end: true
+ - name: report-status-to-lender
+ type: operation
+ actions:
+ - name: report-status-to-lender
+ functionRef:
+ refName: send-status-to-lender
+ arguments:
+ bookid: ${ .book.id }
+ message: Book ${ .book.title } is already on loan
+ transition: wait-for-lender-response
+ - name: wait-for-lender-response
+ type: switch
+ eventConditions:
+ - name: hold-book
+ eventRef: hold-book-event
+ transition: request-hold
+ - name: decline-book-hold
+ eventRef: decline-hold-event
+ transition: cancel-request
+ defaultCondition:
+ end: true
+ - name: request-hold
+ type: operation
+ actions:
+ - name: request-hold
+ functionRef:
+ refName: request-hold-for-lender
+ arguments:
+ bookid: ${ .book.id }
+ lender: ${ .lender }
+ transition: sleep-two-weeks
+ - name: cancel-request
+ type: operation
+ actions:
+ - name: cancel-request
+ functionRef:
+ refName: cancel-hold-request-for-lender
+ arguments:
+ bookid: ${ .book.id }
+ lender: ${ .lender }
+ transition: sleep-two-weeks
+ - name: sleep-two-weeks
+ type: sleep
+ duration: PT2W
+ transition: get-book-status
+ - name: check-out-book
+ type: operation
+ actions:
+ - name: check-out-book
+ functionRef:
+ refName: check-out-book-with-id
+ arguments:
+ bookid: ${ .book.id }
+ - name: notify-lender-for-checkout
+ functionRef:
+ refName: notify-lender-for-checkout
+ arguments:
+ bookid: ${ .book.id }
+ lender: ${ .lender }
end: true
- - name: Request Hold
- type: operation
- actions:
- - functionRef:
- refName: Request hold for lender
- arguments:
- bookid: "${ .book.id }"
- lender: "${ .lender }"
- transition: Sleep two weeks
- - name: Cancel Request
- type: operation
- actions:
- - functionRef:
- refName: Cancel hold request for lender
- arguments:
- bookid: "${ .book.id }"
- lender: "${ .lender }"
- end: true
- - name: Sleep two weeks
- type: sleep
- duration: PT2W
- transition: Get Book Status
- - name: Check Out Book
- type: operation
- actions:
- - functionRef:
- refName: Check out book with id
- arguments:
- bookid: "${ .book.id }"
- - functionRef:
- refName: Notify Lender for checkout
- arguments:
- bookid: "${ .book.id }"
- lender: "${ .lender }"
- end: true
functions: file://books/lending/functions.json
events: file://books/lending/events.json
```
@@ -4126,87 +4322,90 @@ Its results are then merged back into the state data according to the "toStateDa
```json
{
- "id": "fillglassofwater",
- "name": "Fill glass of water workflow",
- "version": "1.0.0",
- "specVersion": "0.8",
- "start": "Check if full",
- "functions": [
- {
- "name": "Increment Current Count Function",
- "type": "expression",
- "operation": ".counts.current += 1 | .counts.current"
- }
- ],
- "states": [
- {
- "name": "Check if full",
- "type": "switch",
- "dataConditions": [
- {
- "name": "Need to fill more",
- "condition": "${ .counts.current < .counts.max }",
- "transition": "Add Water"
- },
- {
- "name": "Glass full",
- "condition": ".counts.current >= .counts.max",
- "end": true
- }
- ],
- "defaultCondition": {
- "end": true
- }
- },
- {
- "name": "Add Water",
- "type": "operation",
- "actions": [
- {
- "functionRef": "Increment Current Count Function",
- "actionDataFilter": {
- "toStateData": ".counts.current"
- }
- }
- ],
- "transition": "Check if full"
- }
- ]
-}
-```
+ "id": "fillglassofwater",
+ "name": "fillglassofwater",
+ "description": "Fill glass of water workflow",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "start": "check-if-full",
+ "functions": [
+ {
+ "name": "increment-current-count-function",
+ "type": "expression",
+ "operation": ".counts.current += 1 | .counts.current"
+ }
+ ],
+ "states": [
+ {
+ "name": "check-if-full",
+ "type": "switch",
+ "dataConditions": [
+ {
+ "name": "need-to-fill-more",
+ "condition": "${ .counts.current < .counts.max }",
+ "transition": "add-water"
+ },
+ {
+ "name": "glass-full",
+ "condition": ".counts.current >= .counts.max",
+ "end": true
+ }
+ ],
+ "defaultCondition": {
+ "end": true
+ }
+ },
+ {
+ "name": "add-water",
+ "type": "operation",
+ "actions": [
+ {
+ "name": "add-water",
+ "functionRef": "increment-current-count-function",
+ "actionDataFilter": {
+ "toStateData": ".counts.current"
+ }
+ }
+ ],
+ "transition": "check-if-full"
+ }
+ ]
+}```
|
```yaml
id: fillglassofwater
-name: Fill glass of water workflow
-version: '1.0.0'
-specVersion: '0.8'
-start: Check if full
+name: fillglassofwater
+description: Fill glass of water workflow
+version: 1.0.0
+specVersion: "0.8"
+start: check-if-full
functions:
- - name: Increment Current Count Function
- type: expression
- operation: ".counts.current += 1 | .counts.current"
+ - name: increment-current-count-function
+ type: expression
+ operation: .counts.current += 1 | .counts.current
states:
- - name: Check if full
- type: switch
- dataConditions:
- - name: Need to fill more
- condition: "${ .counts.current < .counts.max }"
- transition: Add Water
- - name: Glass full
- condition: ".counts.current >= .counts.max"
+ - name: check-if-full
+ type: switch
+ dataConditions:
+ - name: need-to-fill-more
+ condition: ${ .counts.current < .counts.max }
+ transition: add-water
+ - name: glass-full
+ condition: .counts.current >= .counts.max
+ end: true
+ defaultCondition:
end: true
- defaultCondition:
- end: true
- - name: Add Water
- type: operation
- actions:
- - functionRef: Increment Current Count Function
- actionDataFilter:
- toStateData: ".counts.current"
- transition: Check if full
+ - name: add-water
+ type: operation
+ actions:
+ - name: add-water
+ functionRef: increment-current-count-function
+ actionDataFilter:
+ toStateData: .counts.current
+ transition: check-if-full
```
|
@@ -4497,122 +4696,127 @@ We assume that our workflow input has the runtime-imposed quota:
```json
{
- "id":"notifycustomerworkflow",
- "name":"Notify Customer",
- "version":"1.0",
- "specVersion": "0.8",
- "start":"WaitForCustomerEvent",
- "states":[
- {
- "name":"WaitForCustomerEvent",
- "type":"event",
- "onEvents":[
- {
- "eventRefs":[
- "CustomerEvent"
- ],
- "eventDataFilter":{
- "data":"${ .customerId }",
- "toStateData":"${ .eventCustomerId }"
- },
- "actions":[
- {
- "functionRef":{
- "refName":"NotifyCustomerFunction",
- "arguments":{
- "customerId":"${ .eventCustomerId }"
+ "id": "notifycustomerworkflow",
+ "name": "notifycustomerworkflow",
+ "description": "Notify Customer",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "start": "wait-for-customer-event",
+ "states": [
+ {
+ "name": "wait-for-customer-event",
+ "type": "event",
+ "onEvents": [
+ {
+ "eventRefs": [
+ "customer-event"
+ ],
+ "eventDataFilter": {
+ "data": "${ .customerId }",
+ "toStateData": "${ .eventCustomerId }"
+ },
+ "actions": [
+ {
+ "name": "notify-customer-function",
+ "functionRef": {
+ "refName": "notify-customer-function",
+ "arguments": {
+ "customerId": "${ .eventCustomerId }"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "stateDataFilter": {
+ "output": "${ .count = .count + 1 }"
+ },
+ "transition": "check-event-quota"
+ },
+ {
+ "name": "check-event-quota",
+ "type": "switch",
+ "dataConditions": [
+ {
+ "name": "ready",
+ "condition": "${ try(.customerCount) != null and .customerCount > .quota.maxConsumedEvents }",
+ "end": {
+ "continueAs": {
+ "workflowId": "notifycustomerworkflow",
+ "version": "1.0.0",
+ "data": "${ del(.customerCount) }"
+ }
+ }
+ }
+ ],
+ "defaultCondition": {
+ "transition": "wait-for-customer-event"
+ }
}
- }
- }
- ]
- }
- ],
- "stateDataFilter":{
- "output":"${ .count = .count + 1 }"
- },
- "transition":"CheckEventQuota"
- },
- {
- "name":"CheckEventQuota",
- "type":"switch",
- "dataConditions":[
- {
- "condition":"${ try(.customerCount) != null and .customerCount > .quota.maxConsumedEvents }",
- "end":{
- "continueAs": {
- "workflowId": "notifycustomerworkflow",
- "version": "1.0.0",
- "data": "${ del(.customerCount) }"
- }
- }
- }
- ],
- "defaultCondition":{
- "transition":"WaitForCustomerEvent"
- }
- }
- ],
- "events":[
- {
- "name":"CustomerEvent",
- "type":"org.events.customerEvent",
- "source":"customerSource"
- }
- ],
- "functions":[
- {
- "name":"NotifyCustomerFunction",
- "operation":"http://myapis.org/customerapis.json#notifyCustomer"
- }
- ]
-}
-```
+ ],
+ "events": [
+ {
+ "name": "customer-event",
+ "type": "org.events.customerEvent",
+ "source": "customerSource"
+ }
+ ],
+ "functions": [
+ {
+ "name": "notify-customer-function",
+ "operation": "http://myapis.org/customerapis.json#notifyCustomer"
+ }
+ ]
+}```
```yaml
id: notifycustomerworkflow
-name: Notify Customer
-version: '1.0.0'
-specVersion: '0.8'
-start: WaitForCustomerEvent
+name: notifycustomerworkflow
+description: Notify Customer
+version: 1.0.0
+specVersion: "0.8"
+start: wait-for-customer-event
states:
- - name: WaitForCustomerEvent
- type: event
- onEvents:
- - eventRefs:
- - CustomerEvent
- eventDataFilter:
- data: "${ .customerId }"
- toStateData: "${ .eventCustomerId }"
- actions:
- - functionRef:
- refName: NotifyCustomerFunction
- arguments:
- customerId: "${ .eventCustomerId }"
- stateDataFilter:
- output: "${ .count = .count + 1 }"
- transition: CheckEventQuota
- - name: CheckEventQuota
- type: switch
- dataConditions:
- - condition: "${ try(.customerCount) != null and .customerCount > .quota.maxConsumedEvents
- }"
- end:
- continueAs:
- workflowId: notifycustomerworkflow
- version: '1.0.0'
- data: "${ del(.customerCount) }"
- defaultCondition:
- transition: WaitForCustomerEvent
+ - name: wait-for-customer-event
+ type: event
+ onEvents:
+ - eventRefs:
+ - customer-event
+ eventDataFilter:
+ data: ${ .customerId }
+ toStateData: ${ .eventCustomerId }
+ actions:
+ - name: notify-customer-function
+ functionRef:
+ refName: notify-customer-function
+ arguments:
+ customerId: ${ .eventCustomerId }
+ stateDataFilter:
+ output: ${ .count = .count + 1 }
+ transition: check-event-quota
+ - name: check-event-quota
+ type: switch
+ dataConditions:
+ - name: ready
+ condition: ${ try(.customerCount) != null and .customerCount >
+ .quota.maxConsumedEvents }
+ end:
+ continueAs:
+ workflowId: notifycustomerworkflow
+ version: 1.0.0
+ data: ${ del(.customerCount) }
+ defaultCondition:
+ transition: wait-for-customer-event
events:
- - name: CustomerEvent
- type: org.events.customerEvent
- source: customerSource
+ - name: customer-event
+ type: org.events.customerEvent
+ source: customerSource
functions:
- - name: NotifyCustomerFunction
- operation: http://myapis.org/customerapis.json#notifyCustomer
+ - name: notify-customer-function
+ operation: http://myapis.org/customerapis.json#notifyCustomer
```
|
@@ -4659,81 +4863,82 @@ decide which activity to perform based on the transaction value.
```json
{
- "id": "customerbankingtransactions",
- "name": "Customer Banking Transactions Workflow",
- "version": "1.0.0",
- "specVersion": "0.8",
- "autoRetries": true,
- "constants": {
- "largetxamount" : 5000
- },
- "states": [
- {
- "name": "ProcessTransactions",
- "type": "foreach",
- "inputCollection": "${ .customer.transactions }",
- "iterationParam": "${ .tx }",
- "actions": [
- {
- "name": "Process Larger Transaction",
- "functionRef": "Banking Service - Larger Tx",
- "condition": "${ .tx >= $CONST.largetxamount }"
+ "id": "customerbankingtransactions",
+ "name": "customerbankingtransactions",
+ "description": "Customer Banking Transactions Workflow",
+ "version": "1.0.0",
+ "specVersion": "0.8",
+ "autoRetries": true,
+ "constants": {
+ "largetxamount": 5000
},
- {
- "name": "Process Smaller Transaction",
- "functionRef": "Banking Service - Smaller Tx",
- "condition": "${ .tx < $CONST.largetxamount }"
- }
- ],
- "end": true
- }
- ],
- "functions": [
- {
- "name": "Banking Service - Larger Tx",
- "type": "asyncapi",
- "operation": "banking.yaml#largerTransation"
- },
- {
- "name": "Banking Service - Smaller T",
- "type": "asyncapi",
- "operation": "banking.yaml#smallerTransation"
- }
- ]
-}
-```
+ "states": [
+ {
+ "name": "process-transactions",
+ "type": "foreach",
+ "inputCollection": "${ .customer.transactions }",
+ "iterationParam": "${ .tx }",
+ "actions": [
+ {
+ "name": "process-larger-transaction",
+ "functionRef": "banking-service-larger-tx",
+ "condition": "${ .tx >= $CONST.largetxamount }"
+ },
+ {
+ "name": "process-smaller-transaction",
+ "functionRef": "banking-service-smaller-tx",
+ "condition": "${ .tx < $CONST.largetxamount }"
+ }
+ ],
+ "end": true
+ }
+ ],
+ "functions": [
+ {
+ "name": "banking-service-larger-tx",
+ "type": "asyncapi",
+ "operation": "banking.yaml#largerTransation"
+ },
+ {
+ "name": "banking-service-smaller-tx",
+ "type": "asyncapi",
+ "operation": "banking.yaml#smallerTransation"
+ }
+ ]
+}```
```yaml
id: customerbankingtransactions
-name: Customer Banking Transactions Workflow
-version: '1.0.0'
-specVersion: '0.8'
+name: customerbankingtransactions
+description: Customer Banking Transactions Workflow
+version: 1.0.0
+specVersion: "0.8"
autoRetries: true
constants:
- largetxamount: 5000
+ largetxamount: 5000
states:
- - name: ProcessTransactions
- type: foreach
- inputCollection: "${ .customer.transactions }"
- iterationParam: "${ .tx }"
- actions:
- - name: Process Larger Transaction
- functionRef: Banking Service - Larger Tx
- condition: "${ .tx >= $CONST.largetxamount }"
- - name: Process Smaller Transaction
- functionRef: Banking Service - Smaller Tx
- condition: "${ .tx < $CONST.largetxamount }"
- end: true
+ - name: process-transactions
+ type: foreach
+ inputCollection: ${ .customer.transactions }
+ iterationParam: ${ .tx }
+ actions:
+ - name: process-larger-transaction
+ functionRef: banking-service-larger-tx
+ condition: ${ .tx >= $CONST.largetxamount }
+ - name: process-smaller-transaction
+ functionRef: banking-service-smaller-tx
+ condition: ${ .tx < $CONST.largetxamount }
+ end: true
functions:
- - name: Banking Service - Larger Tx
- type: asyncapi
- operation: banking.yaml#largerTransation
- - name: Banking Service - Smaller T
- type: asyncapi
- operation: banking.yaml#smallerTransation
+ - name: banking-service-larger-tx
+ type: asyncapi
+ operation: banking.yaml#largerTransation
+ - name: banking-service-smaller-tx
+ type: asyncapi
+ operation: banking.yaml#smallerTransation
```
|
diff --git a/examples/README_TEMPLATE.md b/examples/README_TEMPLATE.md
new file mode 100644
index 00000000..02112ed9
--- /dev/null
+++ b/examples/README_TEMPLATE.md
@@ -0,0 +1,1829 @@
+# Examples
+
+Provides Serverless Workflow language examples
+
+## Table of Contents
+
+- [Hello World](#Hello-World-Example)
+- [Greeting](#Greeting-Example)
+- [Event-based greeting (Event State)](#Event-Based-Greeting-Example)
+- [Solving Math Problems (ForEach state)](#Solving-Math-Problems-Example)
+- [Parallel Execution](#Parallel-Execution-Example)
+- [Async Function Invocation](#Async-Function-Invocation-Example)
+- [Async SubFlow Invocation](#Async-SubFlow-Invocation-Example)
+- [Event Based Transitions (Event-based Switch)](#Event-Based-Transitions-Example)
+- [Applicant Request Decision (Data-based Switch + SubFlows)](#Applicant-Request-Decision-Example)
+- [Provision Orders (Error Handling)](#Provision-Orders-Example)
+- [Monitor Job for completion (Polling)](#Monitor-Job-Example)
+- [Send CloudEvent on Workflow Completion](#Send-CloudEvent-On-Workflow-Completion-Example)
+- [Monitor Patient Vital Signs (Event state)](#Monitor-Patient-Vital-Signs-Example)
+- [Finalize College Application (Event state)](#Finalize-College-Application-Example)
+- [Perform Customer Credit Check (Callback state)](#Perform-Customer-Credit-Check-Example)
+- [Handle Car Auction Bids (Scheduled start Event state)](#Handle-Car-Auction-Bids-Example)
+- [Check Inbox Periodically (Cron-based Workflow start)](#Check-Inbox-Periodically)
+- [Event-based service invocation (Event triggered actions)](#Event-Based-Service-Invocation)
+- [Reusing Function and Event Definitions](#Reusing-Function-And-Event-Definitions)
+- [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 Repeat)](#Car-Vitals-Checks)
+- [Book Lending Workflow](#Book-Lending)
+- [Filling a glass of water (Expression functions)](#Filling-a-glass-of-water)
+- [Online Food Ordering](#Online-Food-Ordering)
+- [Continuing as a new Execution](#Continuing-as-a-new-Execution)
+- [Process Transactions (Foreach State with conditions)](#Process-Transactions)
+
+### Hello World Example
+
+#### Description
+
+In this simple example we use an [Inject State](../specification.md#Inject-State) to inject
+`Hello World` in the states data (as the value of the 'result' property).
+After the state execution completes, since it is an end state, its data output becomes the workflow
+data output, which is:
+
+```json
+{
+ "result": "Hello World"
+}
+```
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Greeting Example
+
+#### Description
+
+This example shows a single [Operation State](../specification.md#operation-state) with one action that calls the "greeting" function.
+The workflow data input is assumed to be the name of the person to greet:
+
+```json
+{
+ "person": {
+ "name": "John"
+ }
+}
+```
+
+The results of the action is assumed to be the greeting for the provided persons name:
+
+```json
+{
+ "greeting": "Welcome to Serverless Workflow, John!"
+}
+```
+
+Which is added to the states data and becomes the workflow data output.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Event Based Greeting Example
+
+#### Description
+
+This example shows a single [Event State](../specification.md#event-state) with one action that calls the "greeting" function.
+The event state consumes cloud events of type "greetingEventType". When an event with this type
+is consumed, the Event state performs a single action that calls the defined "greeting" function.
+
+For the sake of the example we assume that the cloud event we will consume has the format:
+
+```json
+{
+ "specversion" : "1.0",
+ "type" : "greetingEventType",
+ "source" : "greetingEventSource",
+ "data" : {
+ "greet": {
+ "name": "John"
+ }
+ }
+}
+```
+
+The results of the action is assumed to be the full greeting for the provided persons name:
+
+```json
+{
+ "payload": {
+ "greeting": "Welcome to Serverless Workflow, John!"
+ }
+}
+```
+
+Note that in the workflow definition you can see two filters defined. The event data filter defined inside the consume element:
+
+```json
+{
+ "eventDataFilter": {
+ "data": "${ .data.greet } "
+ }
+}
+```
+
+which is triggered when the greeting event is consumed. It extracts its "data.greet" of the event data (payload) and
+merges it with the state data.
+
+The second, a state data filter, which is defined on the event state itself:
+
+```json
+{
+ "stateDataFilter": {
+ "output": "${ .payload.greeting }"
+ }
+}
+```
+
+filters what is selected to be the state data output which then becomes the workflow data output (as it is an end state):
+
+```text
+ "Welcome to Serverless Workflow, John!"
+```
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Solving Math Problems Example
+
+#### Description
+
+In this example we show how to iterate over data using the [ForEach State](../specification.md#foreach-state).
+The state will iterate over a collection of simple math expressions which are
+passed in as the workflow data input:
+
+```json
+ {
+ "expressions": ["2+2", "4-1", "10x3", "20/2"]
+ }
+```
+
+The ForEach state will execute a single defined operation state for each math expression. The operation
+state contains an action which calls a serverless function which actually solves the expression
+and returns its result.
+
+Results of all math expressions are accumulated into the data output of the ForEach state which become the final
+result of the workflow execution.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Parallel Execution Example
+
+#### Description
+
+This example uses a [Parallel State](../specification.md#parallel-state) to execute two branches (simple wait states) at the same time.
+The completionType type is set to "allOf", which means the parallel state has to wait for both branches
+to finish execution before it can transition (end workflow execution in this case as it is an end state).
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+We assume that the two referenced workflows, namely `shortdelayworkflowid` and `longdelayworkflowid` both include a single delay state,
+with the `shortdelayworkflowid` workflow delay state defining its `timeDelay` property to be shorter than that of the `longdelayworkflowid` workflows
+delay state.
+
+### Async Function Invocation Example
+
+#### Description
+
+This example uses a [Operation State](../specification.md#operation-state) to invoke a function async.
+This functions sends an email to a customer.
+Async function execution is a "fire-and-forget" type of invocation. The function is invoked and workflow execution
+does not wait for its results.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Async SubFlow Invocation Example
+
+#### Description
+
+This example uses a [Operation State](../specification.md#operation-state) to invoke a [SubFlow](../specification.md#Subflow-Action) async.
+This SubFlow is responsible for performing some customer business logic.
+Async SubFlow invocation is a "fire-and-forget" type of invocation. The SubFlow is invoked and workflow execution
+does not wait for its results. In addition, we specify that the SubFlow should be allowed to continue its execution
+event if the parent workflow completes its own execution. This is done by defining the actions `onParentComplete`
+property to `continue`.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+For the sake of the example, the definition of "customeronboardingworkflow" workflow invoked as a SubFlow
+is not shown.
+
+### Event Based Transitions Example
+
+#### Description
+
+In this example we use an Event-based [Switch State](../specification.md#switch-state) to wait for arrival
+of the "VisaApproved", or "VisaRejected" Cloud Events. Depending on which type of event happens,
+the workflow performs a different transition. If none of the events arrive in the defined 1 hour timeout
+period, the workflow transitions to the "HandleNoVisaDecision" state.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Applicant Request Decision Example
+
+#### Description
+
+This example shows off the [Switch State](../specification.md#switch-state) and the subflow action. The workflow is started with application information data as input:
+
+```json
+ {
+ "applicant": {
+ "fname": "John",
+ "lname": "Stockton",
+ "age": 22,
+ "email": "js@something.com"
+ }
+ }
+```
+
+We use the switch state with two conditions to determine if the application should be made based on the applicants age.
+If the applicants age is over 18 we start the application (subflow action). Otherwise the workflow notifies the
+ applicant of the rejection.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Provision Orders Example
+
+#### Description
+
+In this example we show off the states error handling capability. The workflow data input that's passed in contains
+missing order information that causes the function in the "ProvisionOrder" state to throw a runtime exception. With the "onErrors" definition we
+can transition the workflow to different error handling states. Each type of error
+in this example is handled by simple delay states. If no errors are encountered the workflow can transition to the "ApplyOrder" state.
+
+Workflow data is assumed to me:
+
+```json
+ {
+ "order": {
+ "id": "",
+ "item": "laptop",
+ "quantity": "10"
+ }
+ }
+```
+
+The data output of the workflow contains the information of the exception caught during workflow execution.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Monitor Job Example
+
+#### Description
+
+In this example we submit a job via an operation state action (serverless function call). It is assumed that it takes some time for
+the submitted job to complete and that it's completion can be checked via another separate serverless function call.
+
+To check for completion we first wait 5 seconds and then get the results of the "CheckJob" serverless function.
+Depending on the results of this we either return the results or transition back to waiting and checking the job completion.
+This is done until the job submission returns "SUCCEEDED" or "FAILED" and the job submission results are reported before workflow
+finishes execution.
+
+In the case job submission raises a runtime error, we transition to an Operation state which invokes
+ a sub-flow responsible for handling the job submission issue.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Send CloudEvent On Workflow Completion Example
+
+#### Description
+
+This example shows how we can produce a CloudEvent on completion of a workflow. Let's say we have the following
+workflow data containing orders that need to be provisioned by our workflow:
+
+```json
+{
+ "orders": [{
+ "id": "123",
+ "item": "laptop",
+ "quantity": "10"
+ },
+ {
+ "id": "456",
+ "item": "desktop",
+ "quantity": "4"
+ }]
+}
+```
+
+Our workflow in this example uses a ForEach state to provision the orders in parallel. The "provisionOrder" function
+used is assumed to have the following results:
+
+```json
+{
+ "id": "123",
+ "outcome": "SUCCESS"
+}
+```
+
+After orders have been provisioned the ForEach states defines the end property which stops workflow execution.
+It defines its end definition to be of type "event" in which case a CloudEvent will be produced which can be consumed
+by other orchestration workflows or other interested consumers.
+
+Note that we define the event to be produced in the workflows "events" property.
+
+The data attached to the event contains the information on provisioned orders by this workflow. So the produced
+CloudEvent upon completion of the workflow could look like:
+
+```json
+{
+ "specversion" : "1.0",
+ "type" : "provisionCompleteType",
+ "datacontenttype" : "application/json",
+ ...
+ "data": {
+ "provisionedOrders": [
+ {
+ "id": "123",
+ "outcome": "SUCCESS"
+ },
+ {
+ "id": "456",
+ "outcome": "FAILURE"
+ }
+ ]
+ }
+}
+```
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Monitor Patient Vital Signs Example
+
+#### Description
+
+In this example a hospital patient is monitored by a Vial Sign Monitoring system. This device can produce three different Cloud Events, namely
+"High Body Temperature", "High Blood Pressure", and "High Respiration Rate".
+Our workflow which needs to take proper actions depending on the event the Vital Sign Monitor produces needs to start
+if any of these events occur. For each of these events a new instance of the workflow is started.
+
+Since the hospital may include many patients that are being monitored it is assumed that all events include a patientId context attribute in the event
+ message. We can use the value of this context attribute to associate the incoming events with the same patient as well as
+ use the patient id to pass as parameter to the functions called by event activities. Here is an example of such event:
+
+```json
+{
+ "specversion" : "1.0",
+ "type" : "org.monitor.highBodyTemp",
+ "source" : "monitoringSource",
+ "subject" : "BodyTemperatureReading",
+ "id" : "A234-1234-1234",
+ "time" : "2020-01-05T17:31:00Z",
+ "patientId" : "PID-12345",
+ "data" : {
+ "value": "98.6F"
+ }
+}
+```
+
+As you can see the "patientId" context attribute of the event includes our correlation key which is the unique
+patient id. If we set it to be the correlation key in our events definition, all events that are considered must
+have the matching patient id.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Finalize College Application Example
+
+#### Description
+
+In this example our workflow is instantiated when all requirements of a college application are completed.
+These requirements include a student submitting an application, the college receiving the students SAT scores, as well
+as a student recommendation letter from a former teacher.
+
+We assume three Cloud Events "ApplicationSubmitted", "SATScoresReceived" and "RecommendationLetterReceived".
+Each include the applicant id in their "applicantId" context attribute, so we can use it to associate these events with an individual applicant.
+
+Our workflow is instantiated and performs the actions to finalize the college application for a student only
+when all three of these events happened (in no particular order).
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Perform Customer Credit Check Example
+
+#### Description
+
+In this example our serverless workflow needs to integrate with an external microservice to perform
+a credit check. We assume that this external microservice notifies a human actor which has to make
+the approval decision based on customer information. Once this decision is made the service emits a CloudEvent which
+includes the decision information as part of its payload.
+The workflow waits for this callback event and then triggers workflow transitions based on the
+credit check decision results.
+
+The workflow data input is assumed to be:
+
+```json
+{
+ "customer": {
+ "id": "customer123",
+ "name": "John Doe",
+ "SSN": 123456,
+ "yearlyIncome": 50000,
+ "address": "123 MyLane, MyCity, MyCountry",
+ "employer": "MyCompany"
+ }
+}
+```
+
+The callback event that our workflow will wait on is assumed to have the following formats.
+For approved credit check, for example:
+
+```json
+{
+ "specversion" : "1.0",
+ "type" : "creditCheckCompleteType",
+ "datacontenttype" : "application/json",
+ ...
+ "data": {
+ "creditCheck": [
+ {
+ "id": "customer123",
+ "score": 700,
+ "decision": "Approved",
+ "reason": "Good credit score"
+ }
+ ]
+ }
+}
+```
+
+And for denied credit check, for example:
+
+```json
+{
+ "specversion" : "1.0",
+ "type" : "creditCheckCompleteType",
+ "datacontenttype" : "application/json",
+ ...
+ "data": {
+ "creditCheck": [
+ {
+ "id": "customer123",
+ "score": 580,
+ "decision": "Denied",
+ "reason": "Low credit score. Recent late payments"
+ }
+ ]
+ }
+}
+```
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Handle Car Auction Bids Example
+
+#### Description
+
+In this example our serverless workflow needs to handle bits for an online car auction. The car auction has a specific start
+and end time. Bids are only allowed to be made during this time period. All bids before or after this time should not be considered.
+We assume that the car auction starts at 9am UTC on March 20th 2020 and ends at 3pm UTC on March 20th 2020.
+
+Bidding is done via an online application and bids are received as events are assumed to have the following format:
+
+```json
+{
+ "specversion" : "1.0",
+ "type" : "carBidType",
+ "datacontenttype" : "application/json",
+ ...
+ "data": {
+ "bid": [
+ {
+ "carid": "car123",
+ "amount": 3000,
+ "bidder": {
+ "id": "xyz",
+ "firstName": "John",
+ "lastName": "Wayne"
+ }
+ }
+ ]
+ }
+}
+```
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Check Inbox Periodically
+
+#### Description
+
+In this example we show the use of scheduled cron-based start event property. The example workflow checks the users inbox every 15 minutes
+and send them a text message when there are important emails.
+
+The results of the inbox service called is expected to be for example:
+
+```json
+{
+ "messages": [
+ {
+ "title": "Update your health benefits",
+ "from": "HR",
+ "priority": "high"
+ },
+ {
+ "title": "New job candidate resume",
+ "from": "Recruiting",
+ "priority": "medium"
+ },
+ ...
+ ]
+}
+```
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Event Based Service Invocation
+
+#### Description
+
+In this example we want to make a Veterinary appointment for our dog Mia. The vet service can be invoked only
+via an event, and its completion results with the appointment day and time is returned via an event as well.
+
+This shows a common scenario especially inside container environments where some services may not be exposed via
+a resource URI, but only accessible by submitting an event to the underlying container events manager.
+
+For this example we assume that that payload of the Vet service response event includes an "appointment"
+object which contains our appointment info.
+
+This info is then filtered to become the workflow data output. It could also be used to for example send us an
+appointment email, a text message reminder, etc.
+
+For this example we assume that the workflow instance is started given the following workflow data input:
+
+```json
+ {
+ "patientInfo": {
+ "name": "Mia",
+ "breed": "German Shepherd",
+ "age": 5,
+ "reason": "Bee sting",
+ "patientId": "Mia1"
+ }
+ }
+```
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Reusing Function And Event Definitions
+
+#### Description
+
+This example shows how [function](../specification.md#Function-Definition) and [event](../specification.md#Event-Definition) definitions
+can be declared independently and referenced by workflow definitions.
+This is useful when you would like to reuse event and function definitions across multiple workflows. In those scenarios it allows you to make
+changed/updates to these definitions in a single place without having to modify multiple workflows.
+
+For the example we have two files, namely our "functiondefs.json" and "eventdefs.yml" (to show that they can be expressed in either JSON or YAML).
+These hold our function and event definitions which then can be referenced by multiple workflows.
+
+* functiondefs.json
+
+```json
+{
+ "functions": [
+ {
+ "name": "checkFundsAvailability",
+ "operation": "file://myapis/billingapis.json#checkFunds"
+ },
+ {
+ "name": "sendSuccessEmail",
+ "operation": "file://myapis/emailapis.json#paymentSuccess"
+ },
+ {
+ "name": "sendInsufficientFundsEmail",
+ "operation": "file://myapis/emailapis.json#paymentInsufficientFunds"
+ }
+ ]
+}
+```
+
+* eventdefs.yml
+
+```yaml
+events:
+- name: PaymentReceivedEvent
+ type: payment.receive
+ source: paymentEventSource
+ correlation:
+ - contextAttributeName: accountId
+- name: ConfirmationCompletedEvent
+ type: payment.confirmation
+ kind: produced
+
+```
+
+In our workflow definition then we can reference these files rather than defining function and events in-line.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definitions
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### New Patient Onboarding
+
+#### Description
+
+In this example we want to use a workflow to onboard a new patient (at a hospital for example).
+To onboard a patient our workflow is invoked via a "NewPatientEvent" event. This events payload contains the
+patient information, for example:
+
+```json
+{
+ "name": "John",
+ "condition": "chest pains"
+}
+```
+
+When this event is received we want to create a new workflow instance and invoke three services
+sequentially. The first service we want to invoke is responsible to store patient information,
+second is to assign a doctor to a patient given the patient condition, and third to assign a
+new appoitment with the patient and the assigned doctor.
+
+In addition, in this example we need to handle a possible situation where one or all of the needed
+services are not available (the server returns a http 503 (Service Unavailable) error). If our workflow
+catches this error, we want to try to recover from this by issuing retries for the particular
+service invocation that caused the error up to 10 times with three seconds in-between retries.
+If the retries are not successful, we want to just gracefully end workflow execution.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+#### Workflow Demo
+
+This example is used in our Serverless Workflow Hands-on series videos [#1](https://www.youtube.com/watch?v=0gmpuGLP-_o)
+and [#2](https://www.youtube.com/watch?v=6A6OYp5nygg).
+
+### Purchase order deadline
+
+#### Description
+
+In this example our workflow processes purchase orders. An order event triggers instance of our workflow.
+To complete the created order, our workflow must first wait for an order confirmation event (correlated to the
+order id), and then wait for the shipment sent event (also correlated to initial order id).
+We do not want to place an exact timeout limit for waiting for the confirmation and shipment events,
+as this might take a different amount of time depending on the size of the order. However we do have the requirement
+that a total amount of time for the order to be confirmed, once its created, is 30 days.
+If the created order is not completed within 30 days it needs to be automatically closed.
+
+This example shows the use of the workflow [execTimeout definition](../specification.md#ExecTimeout-Definition).
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Accumulate room readings
+
+#### Description
+
+In this example we have two IoT sensors for each room in our house. One reads temperature values
+and the other humidity values of each room. We get these measurements for each of our rooms
+as CloudEvents. We can correlate events send by our sensors by the room it is in.
+
+For the example we want to accumulate the temperature and humidity values for each and send hourly reports
+to the home owner for each room.
+
+**Note:** In this example each rooms measurements will be accumulated by a single workflow instance per room.
+Once we receive events for 1 hour (per room) each of the room-based workflow instances will create the report. Events
+consumed after the report is created will trigger a new instance of our workflow (again, per room), accumulate
+the data for an hour, send report, and so on.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### 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 "CarTurnedOnEvent" event and stop when the "CarTurnedOffEvent" event is consumed.
+While the car is driving our workflow should repeatedly check the vitals every 1 second.
+
+For this example we use the workflow [SubFlow](../specification.md#SubFlow-Action) actions to perform the vital checks.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+We fist define our top-level workflow for this example:
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+And then our reusable sub-workflow which performs the checking of our car vitals:
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+```yaml
+id: vitalscheck
+name: Car Vitals Check
+version: '1.0.0'
+specVersion: '0.8'
+start: CheckVitals
+states:
+ - name: CheckVitals
+ type: operation
+ actions:
+ - functionRef: Check Tire Pressure
+ - functionRef: Check Oil Pressure
+ - functionRef: Check Coolant Level
+ - functionRef: Check Battery
+ end:
+ produceEvents:
+ - eventRef: DisplayChecksOnDashboard
+ data: "${ .evaluations }"
+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
+```
+
+ |
+
+
+
+### Book Lending
+
+#### Description
+
+In this example we want to create a book lending workflow. The workflow starts when a lender
+submits a book lending request (via event "Book Lending Request Event").
+The workflow describes our business logic around lending a book, from checking its current availability,
+to waiting on the lender's response if the book is currently not available, to checking out the book and notifying
+the lender.
+
+This example expects the "Book Lending Request Event" event to have a payload of for example:
+
+```json
+{
+ "book": {
+ "title": " ... ",
+ "id": " ... "
+ },
+ "lender": {
+ "name": "John Doe",
+ "address": " ... ",
+ "phone": " ... "
+ }
+}
+```
+
+where the "book" property defines the book to be lent out, and the "lender" property provides info
+about the person wanting to lend the book.
+
+For the sake of the example we assume the functions and event definitions are defined in separate JSON files.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Filling a glass of water
+
+#### Description
+
+In this example we showcase the power of [expression functions](../specification.md#Using-Functions-For-Expression-Evaluation).
+Our workflow definition is assumed to have the following data input:
+
+```json
+{
+ "counts": {
+ "current": 0,
+ "max": 10
+ }
+}
+```
+
+Our workflow simulates filling up a glass of water one "count" at a time until "max" count is reached which
+represents our glass is full.
+Each time we increment the current count, the workflow checks if we need to keep refilling the glass.
+If the current count reaches the max count, the workflow execution ends.
+To increment the current count, the workflow invokes the "IncrementCurrent" expression function.
+Its results are then merged back into the state data according to the "toStateData" property of the event data filter.
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Online Food Ordering
+
+#### Description
+
+In this example we want to create an online food ordering workflow. The below image outlines the workflow
+structure and the available services:
+
+
+
+
+
+Our workflow starts with the "Place Order" [Subflow](../specification.md#SubFlow-Action), which is responsible
+to send the received order to the requested restaurant and the estimated order ETA.
+We then wait for the ETA time when our workflow should go into the "Deliver Order" SubFlow, responsible
+for dispatching a Courier and sending her/him off to pick up the order. Once the order is picked up, the Courier needs to deliver the order to the customer.
+After the order has been delivered to the customer, our workflow needs to charge the customer.
+
+Our workflow needs to communicate with three services during its execution, namely the Order, Delivery, and
+the Payment services.
+
+For the sake of the example, we assume that our workflow can communicate to the Order and Delivery services via REST and the Payment service via gRPC.
+Let's start by defining an example CloudEvent which triggers an instance of our workflow.
+This event can be sent by a web UI, for example, or be pushed onto a Kafka/MQTT topic to start our order workflow.
+
+```json
+{
+ "specversion": "1.0",
+ "type": "org.orders",
+ "source": "/orders/",
+ "subject": "Food Order",
+ "id": "A234-1234-1234",
+ "time": "2021-03-05T17:31:00Z",
+ "orderid": "ORDER-12345",
+ "data": {
+ "id": "ORDER-12345",
+ "customerId": "CUSTOMER-12345",
+ "status": [],
+ "order": {
+ "restaurantId": "RESTAURANT-54321",
+ "items": [
+ {
+ "itemId": "ITEM-8765",
+ "amount": 1,
+ "addons": ""
+ }
+ ]
+ },
+ "delivery":{
+ "address": "1234 MyStreet, MyCountry",
+ "type": "contactless",
+ "requestedTime": "ASAP",
+ "location": "Front door",
+ "instructions": ""
+ }
+ }
+}
+```
+
+Note the `orderid` CloudEvent context attribute, which contains the unique ID of the order specified in this event. [Event correlation](../specification.md#Correlation-Definition) is done against CE context attributes, and as such, to be able
+to correlate multiple order events to the same order id, it needs to be part of the CE context attributes, and
+not its data (payload).
+
+Now let's start defining our workflow. For the sake of this example, let's define our function and event definitions
+as separate YAML files (and then reference them inside our workflow definition). This is useful in cases
+when you want to reuse them between multiple workflow definitions.
+
+#### Workflow Event Definition
+
+``` yaml
+events:
+- name: Food Order Event
+ source: "/orders/"
+ type: org.orders
+ correlation:
+ - contextAttributeName: orderid
+- name: ETA Deadline Event
+ source: "/orderseta"
+ type: org.orders.eta
+ correlation:
+ - contextAttributeName: orderid
+- name: Order Picked Up Event
+ source: "/orderspickup"
+ type: org.orders.delivery
+ correlation:
+ - contextAttributeName: orderid
+- name: Order Delievered Event
+ source: "/orderdelivery"
+ type: org.orders.delivery
+ correlation:
+ - contextAttributeName: orderid
+```
+
+#### Workflow Function Definition
+
+``` yaml
+functions:
+- name: Submit Order Function
+ operation: http://myorderservice.org/orders.json#submit
+- name: Get Order ETA Function
+ operation: http://myorderservice.org/orders.json#orderETA
+- name: Dispatch Courrier Function
+ operation: http://mydeliveryservice.org/deliveries.json#dispatch
+- name: Deliver Order Function
+ operation: http://mydeliveryservice.org/deliveries.json#deliver
+- name: Charge For Order Function
+ operation: http://mypaymentservice.org/payments.proto#PaymentService#ChargeUser
+```
+
+#### Main Workflow Definition
+
+With the function and event definitions in place we can now start writing our main workflow definition:
+
+```yaml
+id: foodorderworkflow
+name: Food Order Workflow
+version: '1.0.0'
+specVersion: '0.8'
+start: Place Order
+functions: file://orderfunctions.yml
+events: file://orderevents.yml
+states:
+- name: Place Order
+ type: operation
+ actions:
+ - subFlowRef: placeorderworkflow
+ transition: Wait for ETA Deadline
+- name: Wait for ETA Deadline
+ type: event
+ onEvents:
+ - eventRefs:
+ - ETA Deadline Event
+ eventDataFilter:
+ data: "${ .results.status }"
+ toStateData: "${ .status }"
+ transition: Deliver Order
+- name: Deliver Order
+ type: operation
+ actions:
+ - subFlowRef: deliverorderworkflow
+ transition: Charge For Order
+- name: Charge For Order
+ type: operation
+ actions:
+ - functionRef:
+ refName: Charge For Order Function
+ arguments:
+ order: "${ .order.id }"
+ actionDataFilter:
+ results: "${ .outcome.status }"
+ toStateData: "${ .status }"
+ stateDataFilter:
+ output: '${ . | {"orderid": .id, "orderstatus": .status} | .orderstatus += ["Order
+ Completed"] }'
+ end: true
+```
+
+With this in place we can start defining our sub-workflows:
+
+#### Place Order Sub-Workflow
+
+```yaml
+id: placeorderworkflow
+name: Place Order Workflow
+version: '1.0.0'
+specVersion: '0.8'
+start: Submit Order
+states:
+- name: Submit Order
+ type: event
+ onEvents:
+ - eventRefs:
+ - Food Order Event
+ actions:
+ - functionRef:
+ refName: Submit Order Function
+ arguments:
+ order: "${ .order }"
+ actionDataFilter:
+ results: "${ .results.status }"
+ toStateData: "${ .status }"
+ - functionRef:
+ refName: Get Order ETA Function
+ arguments:
+ customer: "${ .customerId }"
+ restaurantid: "${ .order.restaurantId }"
+ delivery: " ${ .delivery }"
+ actionDataFilter:
+ results: "${ .results.status }"
+ toStateData: "${ .status }"
+ end: true
+```
+
+#### Deliver Order Sub-Workflow
+
+```yaml
+id: deliverorderworkflow
+name: Deliver Order Workflow
+version: '1.0.0'
+specVersion: '0.8'
+start: Dispatch Courier
+states:
+- name: Dispatch Courier
+ type: operation
+ actions:
+ - functionRef: Dispatch Courrier Function
+ transition: Wait for Order Pickup
+- name: Wait for Order Pickup
+ type: event
+ onEvents:
+ - eventRefs:
+ - Order Picked Up Event
+ eventDataFilter:
+ data: "${ .data.status }"
+ toStateData: "${ .status }"
+ actions:
+ - functionRef: Deliver Order Function
+ transition: Wait for Delivery Confirmation
+- name: Wait for Delivery Confirmation
+ type: event
+ onEvents:
+ - eventRefs:
+ - Order Delievered Event
+ eventDataFilter:
+ data: "${ .data.status }"
+ toStateData: "${ .status }"
+ end: true
+```
+
+#### Workflow Results
+
+For the example order event, the workflow output for a successful completion would look like for example:
+
+```json
+{
+ "orderid": "ORDER-12345",
+ "orderstatus": [
+ "Order Submitted",
+ "Order ETA Received",
+ "Order Picked up",
+ "Order Delievered",
+ "Order Charged",
+ "Order Completed"
+ ]
+}
+```
+
+### Continuing as a new Execution
+
+#### Description
+
+Some runtime implementations on which we run our workflows can have different quotas, such as maximum execution durations, maximum consumed events, etc. We can use the Serverless workflow "continueAs" functionality that can be used to stop the current workflow execution and start another one (of the same or a different type). This is very useful in cases where we have to ensure we don't reach the imposed quotas of single workflow execution.
+
+This example assumes that the runtime we are using has a quota set to a maximum of one thousand consumed events per single workflow execution.
+Our sample workflow consumes a single customer event at a time and invokes the `emailCustomer` function.
+Note that we do not set a workflow `workflowExecTimeout`, so we intend to have a long-running workflow. However, because of the runtime restriction, in this case, we would run into the event consume limit, and our workflow would have to terminate. We can fix this problem by using [`continueAs`](../specification.md#Continuing-as-a-new-Execution), which will allow us to make sure that we reach the given limit and then continue our workflow execution as a new run.
+
+We assume that our workflow input has the runtime-imposed quota:
+
+```json
+{
+ "quota": {
+ "maxConsumedEvents": 1000
+ }
+}
+```
+
+#### Workflow Diagram
+
+
+
+
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
+
+### Process Transactions
+
+#### Description
+
+This example shows how we can loop through a data input array (in parallel), and decide which action to perform
+depending on the value of each element in the input array.
+We use the [action definition](../specification.md#Action-Definition) `condition` property to perform the action that
+is best suited for the transaction value.
+Note that in this example we set the "large transaction amount" as a [workflow constant](../specification.md#Workflow-Constants).
+There are other ways to set
+this value, for example passing it as [workflow data input](../specification.md#Workflow-Data-Input),
+or if this data is sensitive, to use [workflow secrets](../specification.md#Workflow-Secrets).
+
+For the example, we assume the following workflow data input:
+
+```json
+{
+ "customer": {
+ "id": "abc123",
+ "name": "John Doe",
+ "transactions": [1000, 400, 60, 7000, 12000, 250]
+ }
+}
+```
+
+We use the [ForeEach workflow state](../specification.md#ForEach-State) to iterate through customer transactions (in parallel), and
+decide which activity to perform based on the transaction value.
+
+#### Workflow Definition
+
+
+
+ JSON |
+ YAML |
+
+
+
+
+```json
+```
+
+ |
+
+
+```yaml
+```
+
+ |
+
+
diff --git a/examples/roomreadings.json b/examples/accumulate-room-readings.json
similarity index 100%
rename from examples/roomreadings.json
rename to examples/accumulate-room-readings.json
diff --git a/examples/applicantrequest.json b/examples/applicant-request-decision.json
similarity index 100%
rename from examples/applicantrequest.json
rename to examples/applicant-request-decision.json
diff --git a/examples/sendcustomeremail.json b/examples/async-function-invocation.json
similarity index 100%
rename from examples/sendcustomeremail.json
rename to examples/async-function-invocation.json
diff --git a/examples/onboardcustomer.json b/examples/async-subflow-invocation.json
similarity index 100%
rename from examples/onboardcustomer.json
rename to examples/async-subflow-invocation.json
diff --git a/examples/booklending.json b/examples/book-lending.json
similarity index 100%
rename from examples/booklending.json
rename to examples/book-lending.json
diff --git a/examples/vitalscheck.json b/examples/car-vitals-checks-subflow.json
similarity index 100%
rename from examples/vitalscheck.json
rename to examples/car-vitals-checks-subflow.json
diff --git a/examples/checkcarvitals.json b/examples/car-vitals-checks.json
similarity index 100%
rename from examples/checkcarvitals.json
rename to examples/car-vitals-checks.json
diff --git a/examples/checkinbox.json b/examples/check-inbox-periodically.json
similarity index 100%
rename from examples/checkinbox.json
rename to examples/check-inbox-periodically.json
diff --git a/examples/notifycustomerworkflow.json b/examples/continuing-as-a-new-execution.json
similarity index 100%
rename from examples/notifycustomerworkflow.json
rename to examples/continuing-as-a-new-execution.json
diff --git a/examples/eventbasedgreeting.json b/examples/event-based-greeting.json
similarity index 100%
rename from examples/eventbasedgreeting.json
rename to examples/event-based-greeting.json
diff --git a/examples/vetappointmentworkflow.json b/examples/event-based-service-invocation.json
similarity index 100%
rename from examples/vetappointmentworkflow.json
rename to examples/event-based-service-invocation.json
diff --git a/examples/eventbasedswitchstate.json b/examples/event-based-transitions.json
similarity index 100%
rename from examples/eventbasedswitchstate.json
rename to examples/event-based-transitions.json
diff --git a/examples/fillglassofwater.json b/examples/filling-a-glass-of-water.json
similarity index 100%
rename from examples/fillglassofwater.json
rename to examples/filling-a-glass-of-water.json
diff --git a/examples/finalizecollegeapplication.json b/examples/finalize-college-application.json
similarity index 100%
rename from examples/finalizecollegeapplication.json
rename to examples/finalize-college-application.json
diff --git a/examples/handlecarauctionbid.json b/examples/handle-car-auction-bids.json
similarity index 100%
rename from examples/handlecarauctionbid.json
rename to examples/handle-car-auction-bids.json
diff --git a/examples/helloworld.json b/examples/hello-world.json
similarity index 100%
rename from examples/helloworld.json
rename to examples/hello-world.json
diff --git a/examples/jobmonitoring.json b/examples/monitor-job.json
similarity index 100%
rename from examples/jobmonitoring.json
rename to examples/monitor-job.json
diff --git a/examples/patientvitalsworkflow.json b/examples/monitor-patient-vital-signs.json
similarity index 100%
rename from examples/patientvitalsworkflow.json
rename to examples/monitor-patient-vital-signs.json
diff --git a/examples/patientonboard.json b/examples/new-patient-onboarding.json
similarity index 100%
rename from examples/patientonboard.json
rename to examples/new-patient-onboarding.json
diff --git a/examples/parallelexec.json b/examples/parallel-execution.json
similarity index 100%
rename from examples/parallelexec.json
rename to examples/parallel-execution.json
diff --git a/examples/customercreditcheck.json b/examples/perform-customer-credit-check.json
similarity index 100%
rename from examples/customercreditcheck.json
rename to examples/perform-customer-credit-check.json
diff --git a/examples/customerbankingtransactions.json b/examples/process-transactions.json
similarity index 100%
rename from examples/customerbankingtransactions.json
rename to examples/process-transactions.json
diff --git a/examples/provisionorders.json b/examples/provision-orders.json
similarity index 100%
rename from examples/provisionorders.json
rename to examples/provision-orders.json
diff --git a/examples/order.json b/examples/purchase-order-deadline.json
similarity index 100%
rename from examples/order.json
rename to examples/purchase-order-deadline.json
diff --git a/examples/paymentconfirmation.json b/examples/reusing-function-and-event-definitions.json
similarity index 100%
rename from examples/paymentconfirmation.json
rename to examples/reusing-function-and-event-definitions.json
diff --git a/examples/sendcloudeventonprovision.json b/examples/send-cloudevent-on-workflow-completion.json
similarity index 100%
rename from examples/sendcloudeventonprovision.json
rename to examples/send-cloudevent-on-workflow-completion.json
diff --git a/examples/solvemathproblems.json b/examples/solving-math-problems.json
similarity index 100%
rename from examples/solvemathproblems.json
rename to examples/solving-math-problems.json