// Code generated by sqlc. DO NOT EDIT. // versions: // sqlc v1.31.1 // source: idempotency.sql package pgstore import ( "context" "time" ) const completeIdempotencyKey = `-- name: CompleteIdempotencyKey :execrows update idempotency_keys set status = $1, location = $2, body = $3, finished_at = $4, content_sha256 = $5 where user_id = $6 and method = $7 and path_sha256 = $8 and key = $9 and claim_token = $10 and finished_at is null ` type CompleteIdempotencyKeyParams struct { Status *int32 Location string Body []byte FinishedAt *time.Time ContentSha256 []byte UserID string Method string PathSha256 []byte Key string ClaimToken string } // Only the attempt that still HOLDS the claim may write the receipt. func (q *Queries) CompleteIdempotencyKey(ctx context.Context, arg CompleteIdempotencyKeyParams) (int64, error) { result, err := q.db.Exec(ctx, completeIdempotencyKey, arg.Status, arg.Location, arg.Body, arg.FinishedAt, arg.ContentSha256, arg.UserID, arg.Method, arg.PathSha256, arg.Key, arg.ClaimToken, ) if err != nil { return 0, err } return result.RowsAffected(), nil } const insertIdempotencyClaim = `-- name: InsertIdempotencyClaim :execrows insert into idempotency_keys (user_id, method, path, path_sha256, key, request_sha256, claimed_at, claim_token) values ($1, $2, $3, $4, $5, $6, $7, $8) on conflict (user_id, method, path_sha256, key) do nothing ` type InsertIdempotencyClaimParams struct { UserID string Method string Path string PathSha256 []byte Key string RequestSha256 []byte ClaimedAt time.Time ClaimToken string } // `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. func (q *Queries) InsertIdempotencyClaim(ctx context.Context, arg InsertIdempotencyClaimParams) (int64, error) { result, err := q.db.Exec(ctx, insertIdempotencyClaim, arg.UserID, arg.Method, arg.Path, arg.PathSha256, arg.Key, arg.RequestSha256, arg.ClaimedAt, arg.ClaimToken, ) if err != nil { return 0, err } return result.RowsAffected(), nil } const readIdempotencyKey = `-- name: ReadIdempotencyKey :one select request_sha256, status, location, body, claimed_at, finished_at, content_sha256 from idempotency_keys where user_id = $1 and method = $2 and path_sha256 = $3 and key = $4 for update ` type ReadIdempotencyKeyParams struct { UserID string Method string PathSha256 []byte Key string } type ReadIdempotencyKeyRow struct { RequestSha256 []byte Status *int32 Location string Body []byte ClaimedAt time.Time FinishedAt *time.Time ContentSha256 []byte } // The storage half of `Idempotency-Key`. // `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. func (q *Queries) ReadIdempotencyKey(ctx context.Context, arg ReadIdempotencyKeyParams) (ReadIdempotencyKeyRow, error) { row := q.db.QueryRow(ctx, readIdempotencyKey, arg.UserID, arg.Method, arg.PathSha256, arg.Key, ) var i ReadIdempotencyKeyRow err := row.Scan( &i.RequestSha256, &i.Status, &i.Location, &i.Body, &i.ClaimedAt, &i.FinishedAt, &i.ContentSha256, ) return i, err } const releaseIdempotencyKey = `-- name: ReleaseIdempotencyKey :execrows delete from idempotency_keys where user_id = $1 and method = $2 and path_sha256 = $3 and key = $4 and claim_token = $5 and finished_at is null ` type ReleaseIdempotencyKeyParams struct { UserID string Method string PathSha256 []byte Key string ClaimToken string } // 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. func (q *Queries) ReleaseIdempotencyKey(ctx context.Context, arg ReleaseIdempotencyKeyParams) (int64, error) { result, err := q.db.Exec(ctx, releaseIdempotencyKey, arg.UserID, arg.Method, arg.PathSha256, arg.Key, arg.ClaimToken, ) if err != nil { return 0, err } return result.RowsAffected(), nil } const retakeIdempotencyClaim = `-- name: RetakeIdempotencyClaim :exec update idempotency_keys set claimed_at = $1, request_sha256 = $2, claim_token = $3 where user_id = $4 and method = $5 and path_sha256 = $6 and key = $7 ` type RetakeIdempotencyClaimParams struct { ClaimedAt time.Time RequestSha256 []byte ClaimToken string UserID string Method string PathSha256 []byte Key string } // 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. func (q *Queries) RetakeIdempotencyClaim(ctx context.Context, arg RetakeIdempotencyClaimParams) error { _, err := q.db.Exec(ctx, retakeIdempotencyClaim, arg.ClaimedAt, arg.RequestSha256, arg.ClaimToken, arg.UserID, arg.Method, arg.PathSha256, arg.Key, ) return err } const sweepIdempotency = `-- name: SweepIdempotency :execrows delete from idempotency_keys where claimed_at < $1 ` // Forgets records past the window the contract promises ("at least 24 hours"). func (q *Queries) SweepIdempotency(ctx context.Context, before time.Time) (int64, error) { result, err := q.db.Exec(ctx, sweepIdempotency, before) if err != nil { return 0, err } return result.RowsAffected(), nil }