Forja.Event.Schema
(Forja v0.4.0)
View Source
Macro module that provides a DSL for defining typed, validated event schemas using Zoi.
Use this module in event definition modules to get compile-time validated payload schemas with automatic parsing and upcasting support.
Example
defmodule MyApp.Events.OrderCreated do
use Forja.Event.Schema,
event_type: "order:created",
schema_version: 2,
queue: :payments,
forja: :my_app,
source: "checkout"
payload do
field :user_id, Zoi.string()
field :amount_cents, Zoi.integer() |> Zoi.positive()
field :currency, Zoi.string() |> Zoi.default("USD"), required: false
end
def upcast(1, payload) do
%{"user_id" => payload["customer_id"], "amount_cents" => payload["total"]}
end
def idempotency_key(payload) do
"order_created:#{payload["user_id"]}"
end
endWhen :forja is provided, the module also generates emit/1,2 and
emit_multi/2,3 convenience functions:
# Instead of Forja.emit(:my_app, MyApp.Events.OrderCreated, payload: ..., source: ...)
MyApp.Events.OrderCreated.emit(%{user_id: "u123", amount_cents: 500})
# With overrides
MyApp.Events.OrderCreated.emit(%{user_id: "u123", amount_cents: 500},
source: "manual_payment"
)
# In an Ecto.Multi
Ecto.Multi.new()
|> Ecto.Multi.insert(:order, changeset)
|> MyApp.Events.OrderCreated.emit_multi(
payload_fn: fn %{order: o} -> %{user_id: o.user_id, amount_cents: o.total} end
)
|> Forja.transaction(:my_app)Options
:event_type- String identifier for this event type (required):schema_version- Positive integer for payload versioning (default:1):queue- Atom for Oban queue routing, prefixed withforja_internally (default:nil):forja- Atom for the Forja instance name; enablesemit/1,2andemit_multi/2,3(default:nil):source- Default source string for events emitted viaemit/1,2(default:nil)
Generated functions
__forja_event_schema__/0- Returnstrue, marker for runtime detectionevent_type/0- Returns the configured event type stringschema_version/0- Returns the schema version (default: 1)queue/0- Returns the configured queue name ornilparse_payload/1- Validates input against the Zoi schemaupcast/2- Upcasts an old payload version to the current version (overridable)idempotency_key/1- Returns an idempotency key from payload (overridable, default:nil)
When :forja is provided, also generates:
emit/1,2- Emits the event viaForja.emit/3with schema defaultsemit_multi/2,3- Adds event emission to anEcto.MultiviaForja.emit_multi/4
Compile-time validations
- Raises
CompileErrorif:event_typewas not provided - Raises
CompileErrorif no fields were defined inpayload do ... end - Raises
CompileErrorif Zoi is not loaded
Summary
Functions
Defines a payload field with a Zoi type and optional configuration.
Defines a scoped payload block where fields are declared.
Functions
Defines a payload field with a Zoi type and optional configuration.
Arguments
name- The field name (atom)zoi_type- A Zoi type expression (e.g.,Zoi.string(),Zoi.integer() |> Zoi.positive())opts- Optional keyword list. Fields are required by default. Userequired: falseto make a field optional.
Example
field :user_id, Zoi.string()
field :amount, Zoi.integer() |> Zoi.positive()
field :currency, Zoi.string() |> Zoi.default("USD"), required: false
Defines a scoped payload block where fields are declared.
Inside the block, use field/3 to define each payload field.
Example
payload do
field :user_id, Zoi.string(), required: true
field :amount, Zoi.integer()
end