Atomic aggregate in-flight accounting for Tempo fee sponsorship.
Reservations are scoped by chain and sponsor identity and move through
:prepared, :broadcasting, and :pending phases. The store pins one limits
set while reservations are live and rejects divergent configurations.
The guarantee applies to one physical atomic store. MPP.Tempo.ConCacheStore
is suitable for a single BEAM node; every node and endpoint sponsoring the
same wallet must select the same shared backend for a cluster-wide bound.
Reservation expiry is deliberately conservative. A reservation remains live
through its transaction valid_before plus a named clock-skew margin, and the
state-derived store TTL covers that same boundary.
Summary
Types
Fail-closed budget error.
Pinned aggregate sponsor ceilings.
Reservation request accepted by reserve/3.
Functions
Release an owned reservation after a pre-broadcast failure or terminal receipt.
Atomically reserve worst-case sponsor capacity before signing.
Purely remove expired reservations at now.
Move an owned reservation to :broadcasting or {:pending, tx_hash}.
Types
@type error_reason() :: {:capacity_exhausted, pos_integer()} | :incompatible_state | :invalid_request | :limits_mismatch | :ownership_lost | :store_unavailable
Fail-closed budget error.
Opaque ownership handle returned by reserve/3.
@type limits() :: %{ max_in_flight_total_fee: pos_integer(), max_in_flight_reservations: pos_integer() }
Pinned aggregate sponsor ceilings.
@type reservation_params() :: %{ chain_id: non_neg_integer(), sponsor_id: String.t(), fee: pos_integer(), valid_before: pos_integer(), limits: limits() }
Reservation request accepted by reserve/3.
Functions
@spec release(MPP.Tempo.Store.store_ref(), handle(), keyword()) :: :ok | {:error, error_reason()}
Release an owned reservation after a pre-broadcast failure or terminal receipt.
@spec reserve(MPP.Tempo.Store.store_ref(), reservation_params(), keyword()) :: {:ok, handle()} | {:error, error_reason()}
Atomically reserve worst-case sponsor capacity before signing.
Pass :reconcile with a one-argument receipt fetcher to opt into bounded
pending-receipt reconciliation when the budget is at capacity. :now is
available for deterministic tests.
Purely remove expired reservations at now.
Chain-valid reservations remain through valid_before + clock-skew margin;
the exact conservative boundary is retained and removal starts after it.
@spec transition( MPP.Tempo.Store.store_ref(), handle(), :broadcasting | {:pending, String.t()}, keyword() ) :: :ok | {:error, error_reason()}
Move an owned reservation to :broadcasting or {:pending, tx_hash}.
Only the random handle returned by reserve/3 can mutate its reservation.