Metered billing write surface.
Implements Accrue.Billing.report_usage/3 as a sync-through with a
transactional-outbox audit table:
Repo.transact/2inserts apending%MeterEvent{}+ anaccrue_eventsledger row, then commits.- Outside the transaction, calls the configured processor's
report_meter_event/1callback. - On
{:ok, _}→ flips the row toreported(and stampsreported_at). On{:error, _}→Accrue.Billing.MeterEventsperforms a guardedpending→failedtransition and emits[:accrue, :ops, :meter_reporting_failed]at most once for that transition (source: :sync).
Crashes between step 1 and step 2 leave a durable pending row that
Accrue.Jobs.MeterEventsReconciler retries on its next cron tick.
Idempotency: the caller's operation_id (via Accrue.Actor) + event
name + value + timestamp derive a deterministic identifier. The
unique index on accrue_meter_events.identifier dedupes at the audit
layer; Stripe's body-level identifier + HTTP-level idempotency_key
(forwarded in Accrue.Processor.Stripe) dedupe at the wire.
Summary
Functions
Reports a metered usage event. See Accrue.Billing.report_usage/3 for
the public entry point; this function is the implementation target.
Bang variant of report_usage/3.
Functions
@spec report_usage(Accrue.Billing.Customer.t() | String.t(), String.t(), keyword()) :: {:ok, Accrue.Billing.MeterEvent.t()} | {:error, term()}
Reports a metered usage event. See Accrue.Billing.report_usage/3 for
the public entry point; this function is the implementation target.
@spec report_usage!(Accrue.Billing.Customer.t() | String.t(), String.t(), keyword()) :: Accrue.Billing.MeterEvent.t()
Bang variant of report_usage/3.