Skip to content

Conditional Transitions

Oftentimes a flow needs to be a little bit smarter than an immutable sequence of states. That's when conditional transitions are required. For these cases Direktiv provides a switch state which can route the flow based on conditions. Each condition can route the flow to a different state but there can be a defaultTransition to transition to if none of the conditions are true.

Loop Demo
direktiv_api: workflow/v1
functions:
- id: httprequest
  image: gcr.io/direktiv/functions/http-request:1.0
  type: knative-workflow
states:
- id: ifelse
  type: switch
  defaultTransition: done
  conditions:
  - condition: jq(.names)
    transition: poster
- id: poster
  type: action
  action:
    function: httprequest
    input: 
      method: POST
      url: https://jsonplaceholder.typicode.com/posts
      content: 
        name: jq(.names[0])
  transform: jq(del(.names[0]))
  transition: ifelse
- id: done
  type: noop
  transform: done
Input
{
  "names": [
    "Michael",
    "Thomas",
    "Kevin"
  ]
}
Output
{
  "done": "yes"
}

In this example the switch state will transition to poster until the list of names is empty, at which point the flow will transition to the default transition done.

Switch State

The Switch State can make decisions about where to transition to next based on the instance data by evaluating a number of jq expressions and checking the results. Here's an example switch state definition:

- id: ifelse
  type: switch
  conditions:
  - condition: 'jq(.person.age > 18)'
    transition: accept
    #transform:
  - condition: 'jq(.person.age != nil)'
    transition: reject
    #transform:
  defaultTransition: failure
  #defaultTransform:

Each of the conditions will be evaluated in the order it appears by running the jq command in condition. Any result other than null, false, {}, [], "", or 0 will cause the condition to be considered a successful match. If no conditions match the default transition will be used.

Other Conditional Transitions

The Switch State is not the only way to do conditional transitions. The eventsXor state also transitions conditionally based on which CloudEvent was received. All states can also define handlers for catching various types of errors.

Loops

By transitioning to a state that has already happened it's possible to create loops in flow instances. In this example we have got a type of range loop, iterating over the contents of an array. Direktiv sets limits for the number of transitions an instance can make in order to protect itself from infinitely-looping flows. This is an example only and in this case a foreach is a better solution.