Polling-based scheduler that persists alarms to the database and periodically checks for overdue alarms.
This is the default scheduler implementation. It stores alarms in the
durable_object_alarms table and fires them by starting the target
object and calling handle_alarm/2.
Configuration
config :durable_object,
repo: MyApp.Repo,
scheduler: DurableObject.Scheduler.Polling,
scheduler_opts: [
polling_interval: :timer.seconds(30),
claim_ttl: :timer.seconds(60)
]Options
:polling_interval- How often to check for overdue alarms (default: 30 seconds):claim_ttl- How long a claimed alarm waits before being retried (default: 60 seconds)
Crash Recovery
The polling scheduler uses claim-based execution for crash recovery:
- Claim: Before firing, the scheduler atomically sets
claimed_aton the alarm - Fire: The object's
handle_alarm/2callback is invoked - Delete: On success, the alarm is deleted only if still claimed
If a handler reschedules the same alarm, the upsert clears claimed_at, so the
delete becomes a no-op and the new alarm persists. If the handler fails or the
server crashes, the alarm remains claimed and will be retried after claim_ttl
expires.
This provides at-least-once delivery semantics. Handlers should be idempotent.