Workflows #
Workflows are documents written in a database. They correspond to the definition of a Workflow
Workflow documents contain 4 categories of information
- metadata describing the Workflow
- conditions of the Workflow execution
- lifecycle hooks
- actions to be performed if the conditions are validated
Example: Workflow document
{
// metadata
name: 'Cold Chain Workflow Notif',
description: 'Create an alert when the cold chain has been broken',
disabled: true,
payloadPath: '.',
// conditions
trigger: {
type: 'notification',
collection: 'sensors',
filter: {
range: {
temperature: {
gt: 0
}
}
}
},
// actions
actions: [
{
type: 'predicate',
name: 'check-weather',
},
{
type: 'task',
name: 'create-alert',
},
{
type: 'api',
request: {
controller: 'email',
action: 'sendColdChain',
}
}
],
// lifecycle hooks
lifecycle: {
load: {
type: 'request',
request: {
controller: 'server',
action: 'now',
}
}
}
}
Metadata #
Metadata are information about the Workflow:
name
: Workflow namedescription
: Workflow descriptiondisabled
: Workflow statuspayloadPath
: Path to extract a sub-payload (see below to learn more)
{
name: 'Cold Chain Workflow',
description: 'Trigger an alert if the cold chain is broken',
disabled: false,
payloadPath: 'input.body',
// ...
}
Trigger #
The execution conditions of a Workflow consist in a trigger
property that define an action on which the Workflow will start its execution
There are 3 types of triggers:
event
connected to the internal event system of Kuzzlenotification
connected to the real-time notification system.scheduler
using the internal scheduler to trigger the Workflow at a regular interval
Only internal events having a KuzzleRequest as first argument can be used as Workflow trigger.
Payload Extraction #
Each Workflow must define the payloadPath
property to extract a payload from its context. This payload is extracted from the original KuzzleRequest (trigger of type event
) or DocumentNotification (trigger of type notification
) and can be used to match additional filters.
This payload will be referred to during the life-cycle of the Workflow, for example:
- Matched against the filter of a trigger of type event
- Matched against the filter of a Rule
- Added in the body of an action of type API
- Available to developers in the WorkflowContext.payload property
The path of the extracted payload is represented as a lodash path. It is possible to specify the path "."
to use the whole Request or Notification as the Workflow payload.
Example: Use the document content from a document notification as extracted payload
See example
{
// ...
payloadPath: 'result._source',
trigger: {
type: 'notification',
index: 'nyc-open-data',
collection: 'sensors',
filter: {
// set of koncorde filters
}
},
// ...
}
Here the payloadPath
is "result._source"
because the document content is inside this property of DocumentNotification.
{
"index": "tir-open-data",
"collection": "red-taxi",
"controller": "document",
"action": "create",
"protocol": "http",
"timestamp": 1497513122738,
"volatile": null,
"scope": "in",
"node": "knode-nasty-author-4242",
"result":{
"_source": { // <= Extracted payload
"some": "document content",
"_kuzzle_info": {
"author": "-1",
"createdAt": 1497866996975
}
},
"_id": "<document identifier>"
},
"room":"893e183fc7acceb5-7a90af8c8bdaac1b"
}
Event Trigger #
Workflows can be triggered when Kuzzle emits one of its internal events via the Event System.
The trigger.type
property must be set to event
and the trigger.event
property must contain the name of a Kuzzle internal event (e.g. auth:beforeLogin
)
Only internal events having a KuzzleRequest as first argument can be used as Workflow trigger.
It is possible to refine the trigger by using the following properties:
trigger.collection
: a specific collection nametrigger.filter
: a set of Koncorde Filters
Example: Event triggered when a user with a specific email is created
See example
{
// ...
payloadPath: 'input.body.content',
trigger: {
type: 'event',
event: 'security:afterCreateUser',
filter: {
regexp: {
email: '.*@kuzzle\.io$'
}
}
},
// ...
}
This Workflow will be triggered when a user is created with an email address ending with @kuzzle.io
:
kourou security:createUser '{
content: {
profileIds: ["default"],
email: "efsun@kuzzle.io",
},
}'
The extracted payload will contain the user custom content and it will be matched with the Workflow trigger filters.
Engine Events #
By default and for security reasons, an user can only register workflows on engine events.
Engine events are a family of events complying with the following template: engine:<engine-index>:...
(e.g. engine:tenant-shipment-kuzzle:payload:new
)
When using a engine event as a trigger, it's possible to leave the {engine-index}
placeholder instead of the engine index. This placeholder will be replaced by the engine index before registration.
{
// ...
payloadPath: '.',
trigger: {
type: 'event',
event: 'engine:{engine-index}:payload:new',
filter: {}
},
// ...
}
The following internal events are also available as engine events:
document:before*
=>engine:<engine-index>:document:before*
(e.g.engine:tenant-kuzzle:document:beforeCreate
)document:after*
=>engine:<engine-index>:document:after*
(e.g.engine:tenant-kuzzle:document:afterCreate
)generic:document:before*
=>engine:<engine-index>:generic:document:before*
(e.g.engine:tenant-kuzzle:generic:document:beforeCreate
)generic:document:after*
=>engine:<engine-index>:generic:document:after*
(e.g.engine:tenant-kuzzle:generic:document:afterCreate
)
Notification Trigger #
Workflows can be triggered when Kuzzle emits a realtime notification.
The trigger.type
property must be set to notification
. The trigger.collection
and trigger.filter
properties must be set to define a subscription scope.
The subscription scope index will automatically be set to the index containing the Workflow engine.
The Workflow will be triggered whenever a notification matching the subscription scope is generated by Kuzzle.
As real-time notifications can be triggered from backend code, it is important to check that the Workflow cannot trigger itself to avoid infinite loops.
See also Develop with Workflows.
Example: Notification triggered when a sensor detects a break in the cold chain
See example
{
// ...
payloadPath: 'result._source',
trigger: {
type: 'notification',
collection: 'sensors',
filter: {
range: {
temperature: {
gt: 0
}
}
}
},
// ...
}
This Workflow will be triggered each time a document is written with a temperature
property greater than 0 in the collection sensors
of the engine index.
kourou document:create <engine-index> sensors '{
temperature: 2,
}'
By default, the Workflow is only triggered whenever a document enters the subscription scope.
You can change this behavior by modifying the trigger.scope
property. (Default value: in
)
Scheduler trigger #
Workflows can be triggered at a regular interval by the internal Scheduler.
The trigger.type
property must be set to scheduler
and the trigger.schedule
must contains the schedule plan of the workflow.
There is two ways to define a schedule plan:
- using the
cron
syntax: workflow will be triggered at regular interval - using a
timestamp
: workflow will be triggered once at the specified timestamp
The type of the syntax to use is defined by the trigger.schedule.syntax
property and the value of the schedule plan is defined by the trigger.schedule.value
property.
Two other properties will be set automatically by the plugin: - trigger.schedule.humanized
: a human readable version of the schedule plan - trigger.schedule.nextExecution
: the next execution timestamp
Example: Workflow triggered every hour
See example
{
// ...
payloadPath: '.',
trigger: {
type: 'scheduler',
schedule: {
syntax: "cron",
value: "0 * * * *"
}
},
// ...
}
There is no default payload for this trigger type. Instead an empty object will be passed.
It's also possible to define a default payload with the trigger.payload
property.
Actions #
Once the conditions of a Workflow are validated, the Workflow actions can be executed.
These actions are executed sequentially and all share the same execution context so it's possible to pass information between each action. (See also WorkflowContext)
Actions are defined in the actions
array of the Workflow document.
There are 5 types of actions:
api
: execute a Kuzzle API actiontask
: execute a Taskpredicate
: verify a Predicaterule
: execute a Rulerule-group
: execute a group of Rules
API Action #
This action type triggers a call to the Kuzzle API.
The actions[].type
property must be api
and the actions[].request
property must contain a RequestPayload.
API actions will be executed with the rights of the Workflow updater
or author
.
Example: Define a API action to create a document
See example
If you define the following action:
{
// [...]
actions: [
{
type: 'api',
request: {
controller: 'document',
action: 'create',
index: 'engine-index',
body: {
workflowId: '{{ workflowContext.workflow._id }}'
}
collection: 'alerts'
}
}
]
// [...]
}
Then the following request will be sent to Kuzzle:
{
controller: 'document',
action: 'create',
index: 'engine-index',
collection: 'alerts',
body: {
workflowId: '<workflowId>',
}
}
Templated strings #
It's possible to use templated strings inside the request payload to fetch some properties coming from the WorkflowContext
instance or the action initiator.
Templated strings will be dynamically replaced with the given parameters when the action is executed.
The following objects are available:
workflowContext
: theWorkflowContext
instance (e.g.workflowContext.workflow._id
)initiator
: the action initiator, a Rule or a Workflow object (e.g.initiator._id
)
Task Action #
Tasks allow the execution of custom code.
The actions[].type
property must be task
and the actions[].name
property must contain the name of a registered task.
Tasks must be developed and registered within the application code.
See Developing Task to learn how to develop new tasks.
Additional arguments can be passed to a task with the actions[].args
property.
Example: Trigger a task that creates a document and accepts an argument called cold-chain
See example
{
actions: [
{
type: "task",
name: "create-alert",
args: {
type: "cold-chain",
},
},
];
}
Predicate Action #
Predicates allow the execution of custom code to verify a condition.
The actions[].type
property must be predicate
and the actions[].name
property must contain the name of a registered Predicate.
Predicates must be developed and registered within the application code.
See Developing Predicate to learn how to develop new Predicates.
Additional arguments can be passed to a predicate with the actions[].args
property.
Example: Trigger a predicate that checks if it's raining and accepts an argument called city
See example
{
actions: [
{
type: "predicate",
name: "weather-is-raining",
args: {
city: "Kilyos",
},
},
];
}
Rule Action #
You should read the Rules guide to fully understand this part.
Rules allow to conditionnaly execute actions.
The actions[].type
property must be set to rule
and the actions[].name
property must contain the ID of a rule.
Like Workflows, they are composed of conditions to fulfill, and actions to be executed if the conditions are met.
A rule condition is composed of
- a set of koncorde filters that will be matched with the extracted payload.
- an array of predicates to validate
If all conditions are met, then the rule actions are executed.
Rule Group Action #
You should read the Rules guide to fully understand this part.
Rule group action allow to execute several rules in the same action.
The actions[].type
property must be rule-group
and the actions[].name
property must contain the name of a rule group.
Rule groups are defined with the group
property of the rule document.
When a rule group action is executed, all rules within the specified group are loaded. For each rule, the conditions are tested and if they are valid then its actions are executed.
The rules are executed sequentially but in no particular order.
Lifecycle Hooks #
load
#
This hook is executed each time the workflow is loaded:
- when a node is starting
- when the config document is modified
You can execute an API action when the workflow is loaded. It will be executed before trigger registration.
{
// [...]
lifecycle: {
load: {
type: 'request',
request: {
controller: 'server',
action: 'now',
}
}
}
}
Use this hook to initialize data or documents relevant to your workflow configuration