Accrue.Oban.Middleware (accrue v0.2.0)

Copy Markdown View Source

Helper for setting Accrue.Actor operation_id from an Oban job (D3-63).

Call Accrue.Oban.Middleware.put/1 at the top of your worker's perform/1 so the job's processor-side idempotency keys are deterministic across retry attempts:

def perform(%Oban.Job{} = job) do
  Accrue.Oban.Middleware.put(job)
  # ... rest of perform
end

Format: "oban-<job.id>-<job.attempt>". Keying on attempt (not just id) means a retry gets a fresh idempotency key — Stripe will re-process the call rather than return the cached result from the failed attempt. That is usually what you want for a retry.

LiveView integration

LiveView is a hard dependency of accrue_admin only, never accrue. The on_mount hook equivalent (setting operation_id from the LiveView socket's session_id) lives in accrue_admin — see CLAUDE.md for the dependency boundary rule.

Summary

Functions

Stamps the current process with a deterministic operation_id derived from the Oban job id and attempt number. Returns :ok.

Types

job_like()

@type job_like() ::
  Oban.Job.t()
  | %{:id => any(), :attempt => integer(), optional(:args) => map()}

Functions

put(job)

@spec put(job_like()) :: :ok

Stamps the current process with a deterministic operation_id derived from the Oban job id and attempt number. Returns :ok.

Connect account propagation (D5-01)

If the Oban job args include a "stripe_account" key, the connected account id is restored into the process dictionary under :accrue_connected_account_id so downstream Accrue.Processor.Stripe calls pick it up via resolve_stripe_account/1's precedence chain. This mirrors the api-version pdict pattern from D2-14 and keeps Connect context stable across the enqueue → perform boundary.

The middleware only READS stripe_account from trusted enqueue-time args (never from webhook payloads); Oban stores args in jsonb which is trusted DB state, not external input.