47 lines
2.6 KiB
SQL
47 lines
2.6 KiB
SQL
-- The storage half of `Idempotency-Key`.
|
|
|
|
-- name: ReadIdempotencyKey :one
|
|
-- `for update` on a MISSING row locks nothing, which is why the caller has an insert-then-re-read
|
|
-- path behind this and not a bare insert.
|
|
select request_sha256, status, location, body, claimed_at, finished_at, content_sha256
|
|
from idempotency_keys
|
|
where user_id = sqlc.arg(user_id) and method = sqlc.arg(method)
|
|
and path_sha256 = sqlc.arg(path_sha256) and key = sqlc.arg(key) for update;
|
|
|
|
-- name: InsertIdempotencyClaim :execrows
|
|
-- `do nothing` plus a re-read decides between two simultaneous first attempts; a bare insert made
|
|
-- the loser raise a unique violation — a 500 on the one case this header exists for.
|
|
insert into idempotency_keys (user_id, method, path, path_sha256, key, request_sha256, claimed_at, claim_token)
|
|
values (sqlc.arg(user_id), sqlc.arg(method), sqlc.arg(path), sqlc.arg(path_sha256), sqlc.arg(key),
|
|
sqlc.arg(request_sha256), sqlc.arg(claimed_at), sqlc.arg(claim_token))
|
|
on conflict (user_id, method, path_sha256, key) do nothing;
|
|
|
|
-- name: RetakeIdempotencyClaim :exec
|
|
-- The NEW token is what stops the old attempt — which may still be alive and merely slow — from
|
|
-- completing or releasing what is no longer its claim.
|
|
update idempotency_keys
|
|
set claimed_at = sqlc.arg(claimed_at), request_sha256 = sqlc.arg(request_sha256),
|
|
claim_token = sqlc.arg(claim_token)
|
|
where user_id = sqlc.arg(user_id) and method = sqlc.arg(method)
|
|
and path_sha256 = sqlc.arg(path_sha256) and key = sqlc.arg(key);
|
|
|
|
-- name: CompleteIdempotencyKey :execrows
|
|
-- Only the attempt that still HOLDS the claim may write the receipt.
|
|
update idempotency_keys
|
|
set status = sqlc.arg(status), location = sqlc.arg(location), body = sqlc.arg(body),
|
|
finished_at = sqlc.arg(finished_at), content_sha256 = sqlc.arg(content_sha256)
|
|
where user_id = sqlc.arg(user_id) and method = sqlc.arg(method)
|
|
and path_sha256 = sqlc.arg(path_sha256) and key = sqlc.arg(key)
|
|
and claim_token = sqlc.arg(claim_token) and finished_at is null;
|
|
|
|
-- name: ReleaseIdempotencyKey :execrows
|
|
-- On the token for the same reason as the completion: a slow attempt that finally failed used to
|
|
-- delete the row of the successor which had taken the key over and was already doing the work.
|
|
delete from idempotency_keys
|
|
where user_id = sqlc.arg(user_id) and method = sqlc.arg(method)
|
|
and path_sha256 = sqlc.arg(path_sha256) and key = sqlc.arg(key)
|
|
and claim_token = sqlc.arg(claim_token) and finished_at is null;
|
|
|
|
-- name: SweepIdempotency :execrows
|
|
-- Forgets records past the window the contract promises ("at least 24 hours").
|
|
delete from idempotency_keys where claimed_at < sqlc.arg(before);
|