Duplicate Http requests when retrying in Elm 0.19
0 reputation · 01 Jun 2021, 05:27 UTC
0 reputation · 01 Jun 2021, 05:27 UTC
Goal: Ensure that retrying a failed HTTP request does not result in duplicate writes to the backend.
Constraints: Elm’s update function is pure, so emitting the same Msg repeatedly produces the same Cmd; the Http module provides no built‑in retry, backoff, or deduplication mechanisms, and the runtime does not track in‑flight requests.
Uncertainty: The core documentation does not prescribe a canonical way to store pending request identifiers or to generate idempotency keys, leaving the pattern to application code.
30775 reputation · 01 Jun 2021, 15:26 UTC
In Elm 0.19 the Http module does not track in‑flight requests. If the same Msg that triggers an Http.send is emitted again before the previous response is handled, the runtime will emit an identical Cmd, causing the backend to see two identical calls.
Model with a set of pending request identifiers:type alias Model = {
pending : Set String,
-- other fields …
}sendRequest : Request -> Cmd Msg
sendRequest req =
let
id = generateId req -- pure function returning a String
cmd = Http.send ExpectResponse (Http.request { method = "POST", url = "/api/op", body = Http.jsonBody req.payload, headers = [ Http.header "Idempotency-Key" id ] })
in
( { model | pending = Set.insert id model.pending }, cmd )
update, before emitting a retry Msg, check that its ID is not already in pending:update msg model =
case msg of
RetryOp req ->
let id = generateId req
in if Set.member id model.pending then
( model, Cmd.none ) -- duplicate suppressed
else
sendRequest req
ResponseOk _ ->
( { model | pending = Set.delete id model.pending }, Cmd.none )
ResponseErr _ ->
( { model | pending = Set.delete id model.pending }, Cmd.none )
-- …
If your backend supports the Idempotency-Key header, include the same generated ID on every attempt (as shown above). This lets the backend safely ignore retries even if Elm accidentally emits a duplicate Cmd. If the backend does not honor this header, the only guarantee comes from the pending set check in update.
Idempotency-Key header as deduplication?Answering that question determines whether you rely solely on the Elm‑side set or also need the header for safety.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.