AshDispatch.Workers.RetryFailedDeliveries (AshDispatch v0.5.1)
View SourceCron worker that automatically retries failed delivery receipts.
Runs periodically via Oban.Plugins.Cron. Queries for delivery receipts that:
- Have status == :failed (temporary failure)
- Have retry_count < max_retries (default: 5)
- Either haven't been retried yet OR last retry was > retry_delay_minutes ago
- Are not permanently failed (:failed_permanent)
For each eligible receipt:
- Re-enqueues appropriate Oban worker (SendEmail for now)
- Updates receipt status to :scheduled
- Increments retry_count
- Sets last_retry_at timestamp
If a receipt has hit max_retries, it will be marked as :failed_permanent by the SendEmail worker on the final attempt.
Configuration
Configure retry behavior:
config :ash_dispatch,
max_retries: 5, # Max retry attempts before permanent failure
retry_delay_minutes: 15 # Minutes to wait between retriesScheduling
Add to Oban cron config:
config :my_app, Oban,
plugins: [
{Oban.Plugins.Cron,
crontab: [
# Retry failed deliveries every 15 minutes
{"*/15 * * * *", AshDispatch.Workers.RetryFailedDeliveries}
]}
]Exponential Backoff
The retry delay is constant (15 minutes by default), but you can implement exponential backoff by checking retry_count in the worker:
# Custom delay based on retry count
delay_minutes = retry_delay_minutes * (2 ** retry_count)Example Output
[info] RetryFailedDeliveries: Found 3 failed deliveries to retry
[info] Retried delivery: receipt_id=abc123, event=order.created, transport=email, retry_count=2
[info] Retry results: 3 succeeded, 0 failedMonitoring
Track retry metrics in your monitoring system:
- Number of failed receipts retried per run
- Success/failure rate of retries
- Receipts hitting max_retries (becoming :failed_permanent)
Summary
Functions
Processes the retry job.
Queries for eligible failed receipts and retries them.
Returns
:okon success (even if individual retries fail){:error, reason}if the query itself fails
Retry a single failed delivery receipt.
Re-enqueues the appropriate worker based on transport and updates receipt state.
Parameters
receipt- DeliveryReceipt struct to retrymax_retries- Maximum number of retries allowed
Returns
:okon success{:error, reason}on failure