Events
View SourceEvents in AshCommanded represent facts that have occurred in your system. They are the source of truth for the state of your aggregates in the event sourcing pattern. In Commanded, events are immutable facts that describe something that has happened in your domain.
Defining Events
Events are defined in the commanded
DSL extension for Ash resources:
defmodule ECommerce.Customer do
use Ash.Resource,
extensions: [AshCommanded.Commanded.Dsl]
attributes do
uuid_primary_key :id
attribute :email, :string
attribute :name, :string
attribute :status, :string
end
commanded do
events do
event :customer_registered do
fields([:id, :email, :name])
end
event :customer_status_updated do
fields([:id, :status])
end
end
end
end
Event Options
Each event can have the following options:
fields
: List of fields the event containsevent_name
: Override the generated event module name
Generated Event Modules
For each event, AshCommanded generates an event module:
defmodule ECommerce.Events.CustomerRegistered do
@moduledoc """
Event emitted when a customer is registered
"""
@type t :: %__MODULE__{
id: String.t(),
email: String.t(),
name: String.t()
}
defstruct [:id, :email, :name]
end
Event Handling
Events are handled in several ways in AshCommanded:
Aggregate State Updates
In the aggregate module, AshCommanded generates apply/2
functions for each event to update the aggregate state. This follows the Commanded pattern for event-sourced aggregates:
defmodule ECommerce.CustomerAggregate do
defstruct [:id, :email, :name, :status]
def apply(%__MODULE__{} = state, %ECommerce.Events.CustomerRegistered{} = event) do
%__MODULE__{
state |
id: event.id,
email: event.email,
name: event.name
}
end
def apply(%__MODULE__{} = state, %ECommerce.Events.CustomerStatusUpdated{} = event) do
%__MODULE__{
state |
status: event.status
}
end
end
Projections
Projections transform events into resource updates, allowing you to maintain read models. This aligns with the Commanded concept of read model projections. See the Projections documentation for details.
Event Handlers
Event handlers allow you to respond to events with side effects like sending notifications or integrating with external systems. These are implemented as Commanded event handlers. See the Event Handlers documentation for more information.
Choosing Between Projections and Event Handlers
When deciding how to handle events, consider the following:
- Use projections when you need to update your resource state or read models based on events
- Use event handlers when you need to perform side effects like sending notifications, integrating with external systems, or publishing events to other systems
You can use both together to create a complete system that maintains consistent read models while also performing necessary side effects.