Priority Levels
View SourceEvents can declare a delivery priority that flows through the entire dispatch pipeline, enabling consumers to make context-aware delivery decisions.
DSL Usage
dispatch do
# Urgent: bypass timing constraints, always deliver immediately
event :budget_alert,
trigger_on: :manual,
priority: :urgent,
channels: [[transport: :in_app, audience: :user]]
# Standard: deliver at next appropriate opportunity (default)
event :task_completed,
trigger_on: :complete,
priority: :standard,
channels: [[transport: :in_app, audience: :user]]
# Informational: low priority, can be batched or held for summaries
event :habit_logged,
trigger_on: :manual,
priority: :informational,
channels: [[transport: :in_app, audience: :user]]
endIf priority is not specified, it defaults to :standard.
Priority Values
| Priority | Use Case | Example Events |
|---|---|---|
:urgent | Must deliver immediately regardless of context | Billing alerts, security warnings, system failures |
:standard | Deliver at next appropriate opportunity | Task completions, goal achievements, assignment changes |
:informational | Low priority, can be batched or deferred | Habit streaks, pattern detections, weekly summaries |
Pipeline Flow
Priority is set at the event level (not per-channel) because an event's urgency is inherent to what happened, not how it's delivered.
Event DSL (priority: :urgent)
→ InjectDispatchChanges transformer (stores in event_config)
→ DispatchEvent change (sets context.priority)
→ InApp transport (stores in notification.metadata["priority"])
→ Email transport (available in context for custom logic)Where Priority Lives
- Event DSL —
AshDispatch.Resource.Dsl.Event.priority(compile-time) - Event Config —
event_config.priorityin the change opts (transformer-injected) - Context —
%AshDispatch.Context{priority: :urgent}(runtime, during dispatch) - Notification Metadata —
notification.metadata["priority"](in-app, queryable)
Consumer Usage
AshDispatch stores priority but does not enforce delivery rules — that's the consumer's responsibility. This keeps AshDispatch transport-agnostic while enabling rich delivery logic in consuming apps.
Example: Active Hours Gating
# In your app's notification scheduler:
def should_deliver?(notification, user_context) do
priority = notification.metadata["priority"] || "standard"
case priority do
"urgent" -> true # Always deliver
_ -> within_active_hours?(user_context) # Gate non-urgent
end
endExample: Deep Work Suppression
# In your prompt builder:
def show_in_prompt?(notification, flow_mode) do
priority = notification.metadata["priority"] || "standard"
case {priority, flow_mode} do
{"urgent", _} -> true # Urgent always visible
{_, :deep_work} -> false # Suppress during deep work
_ -> true # Otherwise show
end
end