AshDispatch.ReceiptStatus (AshDispatch v0.5.0)
View SourceCentralized receipt status management for AshDispatch workers.
This module provides consistent receipt status updates across all delivery workers (email, webhook, etc.), ensuring uniform behavior and reducing code duplication.
Why This Exists
Receipt status updates were duplicated across multiple workers:
Each had identical mark_sending/1, mark_sent/2, mark_failed/2 functions.
This module consolidates them into a single source of truth.
Status Flow
pending → sending → sent
↘ failed → failed_permanent (after max retries)
↘ scheduled (for async transports)
↘ skipped (user opted out, missing config, etc.)Usage
alias AshDispatch.ReceiptStatus
# In a worker
def perform(%Oban.Job{args: args}) do
with {:ok, receipt} <- get_receipt(args["receipt_id"]),
{:ok, receipt} <- ReceiptStatus.mark_sending(receipt),
{:ok, response} <- do_delivery(receipt) do
ReceiptStatus.mark_sent(receipt, response)
:ok
else
{:error, reason} ->
ReceiptStatus.mark_failed(receipt, reason)
{:error, reason}
end
end
Summary
Functions
Marks a receipt as "failed" (delivery failed, may retry).
Marks a receipt as "failed_permanent" (no more retries).
Marks a receipt as "scheduled" (job enqueued for later delivery).
Marks a receipt as "sending" (delivery in progress).
Marks a receipt as "sent" (delivery successful).
Marks a receipt as "skipped" (intentionally not sent).
Functions
Marks a receipt as "failed" (delivery failed, may retry).
Parameters
receipt- The delivery receipt structreason- Error reason (will be converted to string viainspect/1)
Returns
The updated receipt (raises on failure since this is critical).
Marks a receipt as "failed_permanent" (no more retries).
Used by retry worker when max retries exceeded.
Parameters
receipt- The delivery receipt structerror_message- Final error message
Returns
The updated receipt (raises on failure since this is critical).
Marks a receipt as "scheduled" (job enqueued for later delivery).
Optionally stores the Oban job ID for tracking.
Parameters
receipt- The delivery receipt structopts- Options keyword list:oban_job_id- The Oban job ID (optional)
Returns
The updated receipt (raises on failure since this is critical).
@spec mark_sending(struct()) :: {:ok, struct()} | {:error, Ash.Changeset.t()}
Marks a receipt as "sending" (delivery in progress).
This is called at the start of a delivery attempt.
Returns
{:ok, updated_receipt}on success{:error, changeset}on failure
Marks a receipt as "sent" (delivery successful).
Stores provider response metadata for tracking and debugging.
Parameters
receipt- The delivery receipt structprovider_response- Map with provider details, e.g.,%{id: "msg_123", ...}
Returns
The updated receipt (raises on failure since this is critical).
Marks a receipt as "skipped" (intentionally not sent).
Used when:
- User opted out of notifications
- Required configuration is missing
- Transport is not implemented
Parameters
receipt- The delivery receipt structreason- Reason for skipping (string)
Returns
The updated receipt (raises on failure since this is critical).