Zenaton white logo

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.


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


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

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" });
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;
def on_event(event)
  @address = event.address if event.is_a?(AddressUpdatedEvent)
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.)