Workflow events

Events enable you to inject information into a running workflow instance. For example, if your e-commerce customer wants to change her delivery address it should be possible to do it even after the beginning of the delivery workflow.

Implementation

An event must implement Zenaton\Interfaces\EventInterface, eg.

<?php

use Zenaton\Interfaces\EventInterface;

class AddressUpdatedEvent implements EventInterface
{
    public $address;

    public function __construct($address)
    {
        $this->address = $address;
    }
}

An event is simply defined by a name and some properties.

An event must inherit from the Zenaton::Interfaces::Event, eg.

require 'zenaton'

class AddressUpdatedEvent < Zenaton::Interfaces::Event
  attr_reader :address

  def initialize(address)
    @address = address
  end
end

An event must inherit from the Zenaton.abstracts.event.Event, eg.

from zenaton.abstracts.event import Event

class AddressUpdatedEvent(Event):

  def initialize(self, address):
    self.address = address

Sending to a workflow

You can easily send an event to a workflow:

WelcomeFlow::whereId($email)->send(new AddressUpdatedEvent('One Infinite Loop Cupertino, CA 95014'))
await WelcomeFlow.whereId(email).send("AddressUpdatedEvent", { address: "One Infinite Loop Cupertino, CA 95014" });
client.select.workflow("WelcomeFlow").withTag(email).send("AddressUpdatedEvent", { address: "One Infinite Loop Cupertino, CA 95014" });
WelcomeFlow.where_id(email).send_event(AddressUpdatedEvent.new('One Infinite Loop Cupertino, CA 95014'))
WelcomeFlow().where_id(email).send_event(AddressUpdatedEvent('One Infinite Loop Cupertino, CA 95014'))
WelcomeFlow.WhereID(email).Send("AddressUpdatedEvent", map[string]interface{}{"address": "One Infinite Loop Cupertino, CA 95014"})

Handling by a workflow

Then the workflow instance will handle the event through an onEvent method that will receive the event object as a parameter. For example:

...

public function onEvent(EventInterface $event)
{
    if ($event instanceof AddressUpdatedEvent) {
        $this->address = $event->address;
    }
}
onEvent(name, data) {
  if (name === 'AddressUpdatedEvent') {
    this.address = data.address;
  }
}
*onEvent(name, ...data) {
  if (name === 'AddressUpdatedEvent') {
    this.address = data.address;
  }
}
def on_event(event)
  @address = event.address if event.is_a?(AddressUpdatedEvent)
end
def on_event(self, event):
    if isinstance(event, AddressUpdatedEvent):
        self.address = event.address
...
func (w *Welcome) OnEvent(name string, event interface{}){
    if name == "AddressUpdatedEvent"{
        eventMap = event.(map[string]interface{})
        w.Address = eventMap["address"].(string)
    }
}
...
The onEvent method is called as soon the event is sent and an Agent is available to execute it.
Remember the workflow implementation MUST be idempotent. So the constraints on the onEvent method are the same as the handle method (it must implement a logical flow and NOT the tasks themselves.)