Skip to content

fix(track): release idempotency key when deduction fails (#1138) - #1838

Open
sravan27 wants to merge 1 commit into
useautumn:mainfrom
sravan27:fix-track-idempotency-rollback-1138
Open

sravan27 wants to merge 1 commit into
useautumn:mainfrom
sravan27:fix-track-idempotency-rollback-1138

Conversation

@sravan27

@sravan27 sravan27 commented Jun 6, 2026 •

Copy link
Copy Markdown

Fixes #1138.

The bug

/track calls with an idempotency_key permanently 409 on retry after a single failure. The key is SET NX into Redis with a 24-hour TTL before runRedisTrack/runRedisTrackV3 runs, so if the deduction throws (insufficient balance, transient Redis fault, etc.) the key sits there blocking every retry for the next 24 hours — even though no deduction ever committed.

The fix

Add releaseIdempotencyKey() next to checkIdempotencyKey() — same Redis key layout, just DEL. Then wrap the runRedisTrack / runRedisTrackV3 call in runTrackV2 and runTrackV3 in try/catch. On any throw:

  1. Release the idempotency claim (so a retry can succeed once the cause is resolved).
  2. Re-throw the original error (the caller still sees the real failure — 402, 500, whatever).

This preserves the existing concurrent-request safety — two simultaneous retries still race on SET NX and only one proceeds — while fixing the retry-after-failure path.

I kept this strictly to the body.idempotency_key path. The internal getTrackIdempotencyKey({ctx}) Redis lock used inside executeRedisDeductionV2 is unchanged; that's a per-deduction internal mechanism with its own lifecycle.

Tests

New unit file server/tests/unit/misc/idempotency/checkIdempotencyKey.test.ts — 7/7 green:

Existing handle-track-queue-fallback.test.ts (3/3) and trackIdempotencyKey.test.ts (1/1) still pass.

Notes for the author of #1138

Your proposed "move storage to after success" change works for the retry path you described, but it opens a window where two concurrent retries both pass the (not-yet-set) check and both perform the deduction. The rollback pattern here keeps concurrent-safety intact. I also left body.skip_event and handleEventIdempotencyKey's commented-out event-insert block alone — those are a separate concern (sync-vs-queue event logging) and didn't seem worth bundling into a focused fix.


Summary by cubic

Fixes a bug where /track requests with an idempotency_key returned 409 on every retry after a failed deduction. We now release the key on errors so retries can proceed, while keeping concurrent safety intact.

  • Bug Fixes
    • Added releaseIdempotencyKey() to delete track:<idempotency_key> in Redis when a deduction fails.
    • Wrapped runRedisTrack/runRedisTrackV3 in try/catch inside runTrackV2/runTrackV3; on error, release the key and re-throw.
    • Preserves existing SET NX concurrency guarantees; retries after failure no longer 409.
    • Added unit tests covering release-then-retry, Redis fail-open, and distinct key isolation.

Written for commit 5575252. Summary will update on new commits.

Review in cubic

)

Previously, an idempotency key was SET in Redis with a 24h TTL BEFORE runRedisTrack ran. If the deduction then failed (insufficient balance, transient Redis fault, etc.), the key was permanently 'poisoned' for 24 hours — every retry hit 409 duplicate_idempotency_key, even though no actual deduction had committed.

Fix: add releaseIdempotencyKey() that deletes the Redis key, and wrap runRedisTrack / runRedisTrackV3 in try/catch in runTrackV2 + runTrackV3 — on any error, release the claim before re-throwing the original error. This preserves the original concurrent-request safety (two simultaneous retries still race on SET NX; only one proceeds) AND lets the caller safely retry after a failure.

Unit tests added covering: atomic SET NX, release-then-retry, Redis-not-ready fail-open, swallowed del errors, and no-cross-talk between distinct keys (7/7 passing).
@sravan27
sravan27 requested review from ay-rod and johnyeocx as code owners June 6, 2026 02:42
@greptile-apps

greptile-apps Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

PR author is not in the allowed authors list.

@vercel

vercel Bot commented Jun 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
checkout Ignored Ignored Jun 6, 2026 2:42am
landing-page Ignored Ignored Jun 6, 2026 2:42am

Request Review

@vercel
vercel Bot temporarily deployed to Preview – autumn-vite June 6, 2026 02:42 Inactive
@capy-ai

capy-ai Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

@entelligence-ai-pr-reviews

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5 - Safe to Merge

Safe to merge — this PR correctly addresses an idempotency key leak by ensuring the key is released when a deduction operation fails, preventing resource exhaustion or duplicate-prevention bypass in retry scenarios. The fix is targeted and surgical, touching only the failure path in the track deduction logic without altering the success path or broader control flow. No issues were identified by automated review across all four changed files, and the change aligns well with the stated intent of the fix.

Key Findings:

  • The idempotency key release on deduction failure is a correctness fix — without it, failed deductions would permanently consume their key slot, blocking legitimate retries and potentially causing silent failures in downstream consumers.
  • The change is minimal and scoped exclusively to the error handling path, reducing the risk of unintended side effects on the happy path or other call sites.
  • All four changed files were reviewed and no logic, security, or performance issues were flagged, giving high confidence in the correctness of the implementation.
  • The PR title and description accurately reflect the change, indicating good authorship hygiene and making future bisecting straightforward.

This branch was previously deployed

1 inactive deployment
Preview – autumn-vite — 55752522 Deployed Jun 6, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant