'db:connection-closed' error when retrying writes in Racket's db library
0 reputation · 07 May 2022, 16:38 UTC
0 reputation · 07 May 2022, 16:38 UTC
The Racket db library throws a 'db:connection-closed' exception when a connection is lost during a transaction. The documentation does not specify how retrying such a write should be handled, leaving the developer to decide whether to re‑execute the statement. Re‑execution can result in duplicate rows because the library provides no built‑in duplicate‑write detection or idempotency tracking. Meanwhile, the http client offers a retry keyword for GET requests but not for POST or other state‑changing methods, creating a similar asymmetry for HTTP writes.
Given this gap, should Racket introduce a higher‑level abstraction that safely retries write operations without risking duplication? 1) How might such an abstraction detect whether a write has already been applied after a failure? 2) Could unique constraints or operation IDs be leveraged to enforce idempotency? 3) What trade‑offs would arise from adding automatic retry logic to the db and http libraries?
34775 reputation · 08 May 2022, 02:38 UTC
When a Racket db transaction loses its connection, the library throws a 'db:connection-closed' exception and rolls back the transaction automatically. The library does not provide a built-in retry path, so the developer must decide whether to re-execute the statement. Re-executing can produce duplicate rows unless the write is protected by a unique constraint or an idempotency token.
db library rolls back automatically on 'db:connection-closed.'db:connection-closed' exception. When caught, close the old connection, create a new one, and retry the transaction.operation_id column.operation_id, and check for its existence before performing the write.'db:connection-closed with context; otherwise, return the successful result.The most reliable method is to rely on the database’s unique constraint engine. When the retry is attempted, the second attempt will raise a constraint instead of inserting a duplicate.
Generate a UUID per logical operation, store it in operation_id, and check for its existence before performing the write. This enforces idempotency at the data layer level.
Diagnostic: Does the target table already enforce a unique constraint on the column you are inserting?
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 08 May 2022, 01:47 UTC
The db:connection-closed exception tells the driver that the socket was lost and the connection can no longer be used. It does not guarantee that the in‑flight write was rolled back; the database may have committed it before the network glitch.
operation_id (or similar) that you assign to that write.INSERT … ON CONFLICT DO NOTHING (or an equivalent upsert), that can replace the manual check.Automatic retry of state‑changing calls can mask partial commits and duplicate side effects outside the database (e.g., sent emails). A retry helper should be opt‑in and scoped to operations that can be made idempotent via unique constraints or idempotency keys.