Oban worker for async webhook handler dispatch.
Enqueued by Accrue.Webhook.Ingest in the same transaction as the
webhook event row. Loads the WebhookEvent, projects it to
%Accrue.Webhook.Event{}, and dispatches to the handler chain.
Handler context (ctx)
Besides attempt, max_attempts, webhook_event_id, and endpoint, the
map includes :meter_error_object — the raw Stripe map at
row.data["data"]["object"] when present (else %{}). Meter error
handlers read this key so handle_event/3 can extract usage identifiers
without re-parsing the full signing payload.
Dispatch order
Accrue.Webhook.DefaultHandlerruns first (non-disableable). Connect-scoped events route toAccrue.Webhook.ConnectHandler.- User handlers from
Accrue.Config.webhook_handlers/0run sequentially. - Each handler is rescue-wrapped for crash isolation — a user handler crash is logged and emits telemetry, but does not cause a retry.
Retry policy
25 attempts with exponential backoff. On the final attempt, transitions
the webhook event to :dead status and emits
[:accrue, :ops, :webhook_dlq, :dead_lettered] telemetry. Dead-lettered
events can be replayed via Accrue.Webhooks.DLQ.requeue/1.
Status lifecycle
:received -> :processing -> :succeeded
-> :failed (retryable)
-> :dead (final attempt)