Named inbound event channels that route external events to jobs and workflows.
An EventSource is a named inbound event channel. External systems dispatch events to a source by name, and the source routes them to one or more jobs or workflows via subscriptions. Each subscription can optionally filter on the event payload, so a single source can fan out to multiple targets selectively.
Event Sources vs Event Triggers
Event Sources and Event Triggers serve different purposes:
- Event Sources are inbound channels for receiving external events and routing them to jobs or workflows. They are always-on endpoints that evaluate subscriptions on every dispatch.
- Event Triggers are durable waits used by workflow steps and runs to pause execution until a matching event arrives. They are created by in-flight runs and consumed once.
Event Sources push events into the system. Event Triggers wait for events from within the system.
EventSource Model
The EventSource struct (defined in apps/strait/internal/domain/types.go) contains the following fields:
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier. |
project_id | string | The project this event source belongs to. |
name | string | Human-readable name, used to address the source during dispatch. |
description | string | Optional description of the source's purpose. |
schema | json | Optional JSON Schema for validating inbound event payloads. |
enabled | bool | Whether the source accepts and routes events. Disabled sources reject dispatches. |
created_at | time.Time | Timestamp when the source was created. |
updated_at | time.Time | Timestamp of the last update. |
EventSubscription Model
An EventSubscription binds an event source to a target (a job or workflow). When an event is dispatched to the source, each enabled subscription is evaluated and, if matched, triggers its target.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier. |
source_id | string | Reference to the parent EventSource. |
target_type | string | The kind of target: job or workflow. |
target_id | string | The ID of the target job or workflow. |
filter_expr | json | Optional filter expression evaluated against the event payload. |
enabled | bool | Whether this subscription is active. |
created_at | time.Time | Timestamp when the subscription was created. |
Subscriptions
A subscription connects a source to a target. Two target types are supported:
job-- When matched, a new job run is enqueued withtriggered_by: "event"and the dispatched payload.workflow-- When matched, a new workflow run is triggered with the dispatched payload.
A single event source can have multiple subscriptions, each pointing to a different target and each with its own filter expression. This allows one inbound event to fan out to several jobs and workflows simultaneously.
Filter Expressions
The optional filter_expr field on a subscription controls whether a dispatched event triggers that subscription. When present, the expression is evaluated against the event payload using eventfilter.Eval:
- If the expression evaluates to
true, the subscription fires. - If it evaluates to
false, the subscription is skipped for that event. - If
filter_expris omitted, the subscription fires on every dispatch.
Use filter expressions to route different event shapes through a single source. For example, a webhooks source could route "action": "created" events to one job and "action": "deleted" events to another.
Event Dispatch
The POST /v1/events/dispatch endpoint is the primary entry point for sending events into the system. The dispatch flow works as follows:
- The source is looked up by
namefrom the request body. - If the source is disabled, the dispatch is rejected.
- Each subscription on the source is evaluated:
- The
filter_expr(if present) is evaluated against the event payload. - Matching subscriptions trigger their target (enqueue a job run or start a workflow run).
- The
- The response includes the number of subscriptions that fired:
{
"dispatched": 2,
"source": "webhook-events"
}A disabled event source rejects all dispatches. Subscriptions with enabled: false are also skipped during evaluation, even if their filter expression would match.
Schema Validation
The optional schema field on an event source accepts a JSON Schema definition. When set, inbound event payloads can be validated against this schema before subscriptions are evaluated. This provides a contract between event producers and the source, catching malformed payloads early.
CRUD Lifecycle
Event sources and their subscriptions are managed through the following API operations:
| Operation | Method | Path |
|---|---|---|
| Create source | POST | /v1/event-sources |
| List sources | GET | /v1/event-sources |
| Get source | GET | /v1/event-sources/{sourceID} |
| Update source | PATCH | /v1/event-sources/{sourceID} |
| Delete source | DELETE | /v1/event-sources/{sourceID} |
| Create subscription | POST | /v1/event-sources/{sourceID}/subscriptions |
| List subscriptions | GET | /v1/event-sources/{sourceID}/subscriptions |
| Delete subscription | DELETE | /v1/event-sources/{sourceID}/subscriptions/{subscriptionID} |
Related Concepts
- Event Triggers -- Durable waits for events within workflow steps and runs.
- Jobs -- The unit of work that event subscriptions can target.
- Workflows -- Multi-step orchestrations that event subscriptions can target.