Bazaar.Idempotency.Store behaviour (Bazaar v0.3.0)

Copy Markdown View Source

Storage behaviour for Bazaar.Plugs.Idempotency.

A key goes through two states. reserve/3 claims it atomically before the action runs, so a concurrent duplicate is refused instead of executed twice. put/3 then records the response for replay, or release/2 frees the key when the response was not worth keeping (a 5xx).

Bazaar.Idempotency.ETS is the bundled in-memory store; a deployment with more than one node wants one backed by shared storage.

Summary

Callbacks

Returns the reservation or recorded response for a key.

Records the response for a key, replacing its reservation.

Frees a key so a later request can claim it.

Claims a key. Fails when the key is already reserved or recorded.

Types

fingerprint()

@type fingerprint() :: integer()

reservation()

@type reservation() :: %{fingerprint: fingerprint(), reserved_at: integer()}

response()

@type response() :: %{
  fingerprint: fingerprint(),
  status: pos_integer(),
  body: binary()
}

store()

@type store() :: term()

Callbacks

fetch(store, key)

@callback fetch(store(), key :: String.t()) :: {:ok, reservation() | response()} | :error

Returns the reservation or recorded response for a key.

put(store, key, response)

@callback put(store(), key :: String.t(), response()) :: :ok

Records the response for a key, replacing its reservation.

release(store, key)

@callback release(store(), key :: String.t()) :: :ok

Frees a key so a later request can claim it.

reserve(store, key, reservation)

@callback reserve(store(), key :: String.t(), reservation()) :: :ok | {:error, :taken}

Claims a key. Fails when the key is already reserved or recorded.