DripDrop.Concurrency.AdapterLock (DripDrop v0.1.0)

Copy Markdown View Source

Per-adapter Postgres transaction-scoped advisory lock for outbound dispatch.

Wraps the outbound deliver path so cap-gate evaluation, state transitions, the actual provider send, and counter writes happen serially per adapter. Two concurrent workers targeting the same adapter cannot both pass MinGap, RampCap, and SubCap and burst past their thresholds; the loser receives :locked and the dispatch path defers with "adapter_busy".

Lifecycle dispatch is unaffected — only deliver_outbound/2 calls this.

Summary

Functions

Runs fun inside a transaction holding pg_try_advisory_xact_lock keyed by the adapter's id. Returns {:ok, result} if the lock was acquired and fun completed; :locked if another worker holds the lock right now; or {:error, reason} for DB errors.

Functions

with_lock(map, fun)

@spec with_lock(Ecto.Schema.t(), (-> term())) ::
  {:ok, term()} | :locked | {:error, term()}

Runs fun inside a transaction holding pg_try_advisory_xact_lock keyed by the adapter's id. Returns {:ok, result} if the lock was acquired and fun completed; :locked if another worker holds the lock right now; or {:error, reason} for DB errors.