Chimeway.Webhooks.ProcessFeedbackWorker (chimeway v1.2.0)

Copy Markdown View Source

Oban worker that processes inbound webhook feedback from a durable ingress row.

Job args contain only ingress_id, keeping durable ingress state authoritative instead of reconstructing truth from queue arguments. All correlation data — adapter identity, delivery_id, provider_message_id, normalized_status — is read from the persisted Chimeway.Webhooks.Ingress row rather than carried through Oban job args.

Safe-noop semantics:

  • Hard-deleted ingress rows → :ok (Pitfall 2: race against operator/test cleanup).
  • Already-ignored rows → :ok (idempotent dedup convergence).
  • Already-processed rows → :ok (idempotent re-run on Oban retry).
  • Stale delivery_id → write ingress_state: :ignored, ignored_reason: :delivery_not_found, return :ok.
  • Stale provider_message_id → write ingress_state: :ignored, ignored_reason: :provider_message_id_not_found, return :ok.

The normalize_perform_result/1 table mirrors WorkflowProgressionWorker.normalize_progress_result/1 so all understood-but-ignored outcomes collapse to :ok at the Oban queue boundary.

Security properties:

  • Stale lookups return :ok rather than raising and causing a retry storm.
  • Only ingress_state, ignored_reason, and processed_at are written; no raw job args or provider payload is persisted on the ingress row.
  • String.to_existing_atom/1 is used only on the bounded ~w(succeeded bounced failed) set after canonicalize_status/1. No String.to_atom/1.
  • :ignored and :processed branches return :ok without re-applying side effects, preventing double-attempt rows or double-signal emission on retries.

Backwards-compatibility shim: Two extra perform/1 heads handle the legacy %{"delivery_id" => …} and %{"provider_message_id" => …} arg shapes, protecting in-flight jobs created by older releases. Remove these clauses only in a planned breaking release after operators have had an explicit queue-drain window.