AshDispatch.Channel (AshDispatch v0.6.4)
View SourceRepresents a delivery channel for an event.
A channel specifies:
- Transport - How to deliver (email, in_app, discord, etc.)
- Audience - Who receives (:user, :admin, custom)
- Time - When to deliver (immediate, delayed, scheduled)
- Policy - Delivery policy (:always, :skip_if_read)
- Variant - Template variant (e.g., :admin for admin-specific templates)
Time
:immediate(or{:in, 0}) — deliver now{:in, seconds}— deliver after a relative delay{:at, %DateTime{}}— deliver at an absolute time (a time in the past means now){:window, map}— deprecated, delivers immediately
Only asynchronous transports honour the delay; :in_app writes its
notification synchronously.
Examples
%Channel{
transport: :email,
audience: :user,
time: {:in, 300}, # Delay 5 minutes
policy: :skip_if_read
}
%Channel{
transport: :email,
audience: :user,
time: {:at, ~U[2026-09-01 07:00:00Z]} # Deliver at an absolute time
}
%Channel{
transport: :discord,
audience: :admin,
time: :immediate,
opts: %{webhook_url: "https://..."}
}
Summary
Functions
Calculates delay in seconds from time specification.
Helper function to create a channel struct. Used in DSL and event modules for cleaner syntax.
Checks if a channel matches given transport and/or audience filters.
Creates a new channel.
Normalizes time specification to internal format.
Logs the {:window, map} deprecation once per boot.
Types
@type audience() :: :user | :admin | atom()
@type policy() :: :always | :skip_if_read | {:gate, function()}
@type t() :: %AshDispatch.Channel{ audience: audience(), content: map(), deduplicate_group: atom() | nil, exclude_actor: boolean(), load: [atom() | {atom(), any()}], locale: String.t() | nil, locale_from: atom() | nil, locales: [String.t()], metadata: map(), optional: boolean(), opts: map(), policy: policy(), time: time(), transport: transport(), variant: variant(), webhook_url: String.t() | nil }
@type time() :: :immediate | {:in, non_neg_integer()} | {:at, DateTime.t()} | {:window, map()}
@type transport() :: :email | :in_app | :discord | :sms | :slack | :webhook | atom()
@type variant() :: atom() | nil
Functions
Calculates delay in seconds from time specification.
For {:at, datetime} the result is relative to now and may be negative
when the datetime is in the past; callers that schedule work clamp it at
zero (see AshDispatch.Transports.Email).
{:window, map} is deprecated and always returns 0 (immediate) — see
warn_window_deprecated/0.
Examples
iex> Channel.calculate_delay(%Channel{transport: :email, audience: :user, time: {:in, 300}})
300
iex> Channel.calculate_delay(%Channel{transport: :email, audience: :user, time: :immediate})
0
Helper function to create a channel struct. Used in DSL and event modules for cleaner syntax.
Examples
def channels(_ctx) do
[
channel(:in_app, :user),
channel(:email, :user, time: 5.minutes(), skip_if_read: true)
]
end
Checks if a channel matches given transport and/or audience filters.
Examples
iex> channel = %Channel{transport: :in_app, audience: :user}
iex> Channel.matches?(channel, transport: :in_app)
true
iex> Channel.matches?(channel, transport: :email)
false
iex> Channel.matches?(channel, transport: :in_app, audience: :user)
true
Creates a new channel.
Examples
iex> Channel.new(:email, :user)
%Channel{transport: :email, audience: :user, time: {:in, 0}}
iex> Channel.new(:email, :user, time: 5.minutes(), skip_if_read: true)
%Channel{
transport: :email,
audience: :user,
time: {:in, 300},
policy: :skip_if_read
}
Normalizes time specification to internal format.
Examples
iex> Channel.normalize_time(:immediate)
{:in, 0}
iex> Channel.normalize_time(300)
{:in, 300}
iex> Channel.normalize_time({:in, 300})
{:in, 300}
@spec warn_window_deprecated() :: :ok
Logs the {:window, map} deprecation once per boot.
Business-hours windows were never implemented — a {:window, …} channel
has always delivered immediately, silently. Rather than keep lying, the
time spec is deprecated: it still delivers immediately (removing it would
be a breaking change), but the first channel that uses it after boot says
so in the log.
Returns :ok.