Idempotent replay for requests carrying an Idempotency-Key header.
The first response for a key is stored and replayed verbatim for a repeat of the same request. The same key with a different request body is a conflict and gets a 409. The key is reserved before the action runs, so a concurrent duplicate also gets a 409 instead of executing twice, and the lookup happens before the action, so replaying a completed checkout's completion still returns the original response.
Only 2xx and 4xx responses are kept. A 5xx frees the key so the platform's retry can run the action again.
Usage
# In your supervision tree
children = [Bazaar.Idempotency.ETS, MyAppWeb.Endpoint]
# In your router, after Plug.Parsers has run
pipeline :ucp do
plug Bazaar.Plugs.UCPHeaders
plug Bazaar.Plugs.Idempotency
endBazaar.Idempotency.ETS is for development and single-node deployments. In
production, and always with more than one node, back the plug with a
Bazaar.Idempotency.Store on Cachex or your
database, so keys expire and every node sees the same records.
Options
:store-{module, store}implementingBazaar.Idempotency.Store. Defaults to{Bazaar.Idempotency.ETS, Bazaar.Idempotency.ETS}.:methods- request methods that take part. Defaults to["POST", "PUT", "PATCH"].:reservation_ttl- milliseconds after which an unfinished reservation (a request that crashed before responding) may be taken over. Defaults to 30 seconds.
The key is also available as conn.assigns.idempotency_key and echoed in
the idempotency-key response header.