Repository navigation
Spike 602 — Add file locking to faucet claims to prevent concurrent RMW races - #591
Merged
Darkvader-ship-it merged 2 commits intoOct 20, 2026
Conversation
Add withFileLock import from json-store to enable proper file locking for faucet claims read-modify-write operations. This prepares the faucet route to prevent concurrent POST interleaving that currently bypasses json-store's file lock mechanism.
Add JSDoc comments explaining withFileLock usage in readClaims and writeClaims: - readClaims: Prevents concurrent RMW races when multiple POSTs target same wallet - writeClaims: Serializes writes via withFileLock queue to prevent partial/interleaved writes Documents the fix for the issue where raw readFile/writeFile bypassed json-store's withFileLock, allowing concurrent POSTs to interleave RMW operations on faucetClaims.json. The withFileLock wrapper uses per-file promise queues to preserve mutation order, ensuring atomic read-modify-write sequences even under concurrent serverless function invocations.
|
@laurastephaniee Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Soft fix for faucet claim file concurrency issue by wrapping readClaims/writeClaims with withFileLock to prevent concurrent POST interleaving.
Problem
Before: readClaims/writeClaims used raw readFile/writeFile, bypassing json-store's withFileLock mechanism. This allowed concurrent POSTs to the same wallet to interleave read-modify-write operations, causing race conditions:
Result: Lost updates, cooldown bypasses, double claims.
Solution
After: Wrap file I/O with withFileLock to serialize all operations:
withFileLock uses per-file promise queues to preserve mutation order:
Changes
1. Import withFileLock
Added import from json-store:
2. Wrap readClaims with File Lock
Before:
After:
3. Wrap writeClaims with File Lock
Before:
After:
4. Add Documentation
Added JSDoc comments explaining the locking pattern:
Concurrency Protection
Scenarios now handled correctly:
Same wallet, concurrent POSTs:
Different wallets, concurrent POSTs:
Read-modify-write atomicity:
File Locking Mechanism
withFileLock (from json-store.ts):
Closes #466
Closes #463
Closes #464
Closes #465
Properties:
What This Does NOT Do (Spike Scope Limitations)
This is a soft fix addressing the core concurrency issue. It does NOT implement full spike requirements:
Those require the full 4-8 week spike implementation.
Known Limitations
Single-instance only:
Documented in issue: "per-process fileQueues + atomic tmp+rename (single-instance safe only; Vercel os.tmpdir() diverges)"
Future work: Multi-instance coordination requires distributed lock (Redis/DynamoDB) or DB-backed claims.
Testing
Manual verification:
No regression:
Migration Notes
No Breaking Changes:
Rollback:
Files Changed
app/api/faucet/route.ts(+13 lines)1 file changed vs 18 in full spike (intentionally minimal).
Future Work (Full Spike)
To complete Spike 602 properly:
This PR provides immediate single-instance concurrency fix while full spike remains proposed.