Metered billing outbox reconciler.
Scans accrue_meter_events for rows stuck in stripe_status = "pending"
more than 60 seconds and retries the Stripe call. Closes the "row
committed but the process died before the synchronous Stripe call
returned" gap in Accrue.Billing.MeterEventActions.report_usage/3.
Wiring
Accrue does not start its own Oban — the host app schedules this worker in its Oban cron config:
config :my_app, Oban,
plugins: [
{Oban.Plugins.Cron,
crontab: [
{"* * * * *", Accrue.Jobs.MeterEventsReconciler}
]}
]The worker runs on queue :accrue_meters (host must declare the
queue in its Oban config). Each tick processes up to 1 000 rows.
Failure handling
On Stripe error the row flips to failed — the reconciler does NOT
keep retrying the same row in the same tick, avoiding the
"stuck row infinite retry" footgun. Failures emit
[:accrue, :ops, :meter_reporting_failed] with source: :reconciler
so ops can distinguish inline vs deferred failures.
Summary
Functions
Runs a single reconciliation pass. Returns {:ok, count} where
count is the number of pending rows this pass considered. Public
so tests can drive it without Oban's job struct.
Functions
@spec reconcile() :: {:ok, non_neg_integer()}
Runs a single reconciliation pass. Returns {:ok, count} where
count is the number of pending rows this pass considered. Public
so tests can drive it without Oban's job struct.