Official Plugins (Kuzzle v2.x)
Workflows v0.x
2

This plugin is part of the Kuzzle Enterprise Plan. If you are interested, please contact us.

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

workflow-schema

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 name
  • description: Workflow description
  • disabled: Workflow status
  • payloadPath: 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:

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:

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 name
  • trigger.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 action
  • task: execute a Task
  • predicate: verify a Predicate
  • rule: execute a Rule
  • rule-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: the WorkflowContext 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