-
Notifications
You must be signed in to change notification settings - Fork 0
Events And Destinations
To organise your domain events, EventRouter
requires a class for each event. Those event classes must inherit from EventRouter::Event
base class. For example, you can create a new OrderPlaced
event like:
class OrderPlaced < EventRouter::Event; end
The EventRouter::Event
base class defines some general attributes for the event:
-
uid
: Randomly generated UUID per event -
correlation_id
: Randomly generated UUID -
created_at
: defaults toTime.now
-
payload
: All custom event attributes
When you initialise your event, you can override any of the previous attributes and provide your event attributes:
event_1 = OrderPlaced.new(uid: 'foo', correlation_id: 'bla', attr_1: 1, attr_2: 2)
puts event.payload == { attr_1: 1, attr_2: 2 }
You can set custom options on the event level using event_options
method that accepts a hash. The options will be available through the class and instance options
method. Delivery adapters make use of those options to make routing decisions on event level.
class OrderPlaced < EventRouter::Event
event_options queue: :orders, retry: 5
end
Each event can have one or more destinations. Also, your destinations must have a unique name within the event. If you are using async
type delivery adapter, make sure that you don't rename or remove a destination till all scheduled events are processed.
class OrderPlaced < EventRouter::Event
deliver_to :email_notifier, handler: EmailNotifier
deliver_to :email_notifier_2, handler: EmailNotifier, handler_method: :order_placed_2
end
Define destinations using deliver_to
method. deliver_to
method requires at least two attributes:
- A unique name for the destination. It is used for internal mapping, e.g
email_notifier
-
handler
attribute to define the destination class that should receive the event, e.gEmailNotifier
class OrderPlaced < EventRouter::Event
deliver_to :email_notifier, handler: EmailNotifier
end
Destination also provide more attributes that can be configured to customise its behaviour:
Use this option to customise the name of the handler class method. By default it is set to the event class name, snake_cased.
class OrderPlaced < EventRouter::Event
deliver_to :email_notifier, handler: EmailNotifier, handler_method: :order_placed
end
You can send custom payload for each destination. The payload method will be invoked before calling the handler if the event defines any. Use this option to customise the name of the payload method. By default it is set to the destination name + '_payload'
suffix.
class OrderPlaced < EventRouter::Event
deliver_to :email_notifier, handler: EmailNotifier
deliver_to :email_notifier_2, handler: EmailNotifier, payload_method: :custom_email_notifier_payload
def email_notifier_payload
# [TODO] return custom payload to be sent with the event to the email_notifier destination.
end
def custom_email_notifier_payload
# [TODO] return custom payload to be sent with the event to the email_notifier_2 destination.
end
end
It is also possible to prefetch the payload incase you use async
delivery adapter by enabling this option. In this case, the payload will be fetched before your worker is scheduled.
class OrderPlaced < EventRouter::Event
deliver_to :email_notifier, handler: EmailNotifier, prefetch_payload: true
end
Like events, you can pass any options to the destination and access it through options
method. Delivery adapters make use of those options to make routing decisions on destination level.
class OrderPlaced < EventRouter::Event
deliver_to :mailer, handler: Mailer, queue: :mailer, retry: false
end
Once you have defined your domain event, you will also need to define the handler class. EventRouter
will look by default for a class method with the same event name in the handler.
The handler methods should receive a single hash argument that will have two keys:
- The
event
itself - The custom
payload
, see payload_method options
class EmailNotifier
def self.order_placed(event:, payload:)
# [TODO] Handle the event here
end
end
If payload
is not needed, you can discard the payload:
class EmailNotifier
def self.order_placed(event:, **_payload)
# [TODO] Handle the event here
end
end
EventRouter
does not put any constraints on the handler object, it can be a class as shown in the previous examples, or can be defined as module:
module EmailNotifier
module_function
def order_placed(event:, payload:)
# [TODO] Handle the event here
end
end