Oban worker that delivers a transactional email asynchronously.
Flow
Accrue.Mailer.Default.deliver/2enqueues a job with string-keyed%{"type" => "...", "assigns" => %{...}}args (Oban-safe scalars only).perform/1rehydrates the assigns (locale/timezone/customer hydration viaenrich/2), resolves the template module (honoring:email_overridesrung 2 MFA and rung 3 atom), builds a Mailglass message for the Mailglass mailers, and delivers viaMailglass.deliver/1.
Queue
Host applications MUST configure an Oban queue named :accrue_mailers.
Recommended concurrency: 20.
Idempotency
Delivery-level idempotency uses a business-event key stamped onto the Mailglass message metadata. That keeps the enqueue boundary scalar-only while letting the delivery path dedupe on the approved event key.
Summary
Functions
Enriches raw Oban-arg assigns with locale, timezone, and (optionally)
the hydrated Accrue.Billing.Customer struct (D6-03 precedence ladder).
Resolves the template module for an email type. Honors :email_overrides
(Pay-style ladder D-23)
Functions
Enriches raw Oban-arg assigns with locale, timezone, and (optionally)
the hydrated Accrue.Billing.Customer struct (D6-03 precedence ladder).
Precedence for locale:
assigns[:locale]/assigns["locale"]customer.preferred_locale(hydrated viaassigns[:customer_id])Accrue.Config.default_locale/0- Hardcoded
"en"fallback
Same ladder for timezone (swap preferred_timezone +
Accrue.Config.default_timezone/0 + "Etc/UTC").
Unknown locales/zones emit [:accrue, :email, :locale_fallback] /
[:accrue, :email, :timezone_fallback] telemetry with
%{requested: value} metadata (no PII) and fall back to "en" /
"Etc/UTC". enrich/2 NEVER raises — pitfall 5 defense.
Resolves the template module for an email type. Honors :email_overrides
(Pay-style ladder D-23):
- Rung 2 (MFA):
{Mod, :fun, args}callsMod.fun(type, *args)at runtime, letting hosts pick a template dynamically based on request- time context. The type atom is prepended toargsas the first argument so MFA callbacks receive it. - Rung 3 (atom):
YourModulereplaces the default template module. - No override: falls through to
default_template/1.