Skip to content

Fix race condition in FileStorage dequeue#19

Merged
mcollina merged 1 commit intomainfrom
fix/filestorage-race-condition
Feb 17, 2026
Merged

Fix race condition in FileStorage dequeue#19
mcollina merged 1 commit intomainfrom
fix/filestorage-race-condition

Conversation

@mcollina
Copy link
Copy Markdown
Member

Summary

  • Fix TOCTOU race condition when multiple workers try to claim the same job
  • Use atomic rename() instead of read() + writeFileAtomic() + unlink()

Problem

The previous implementation had a race condition:

const message = await readFile(srcPath)      // 1. Worker A reads
// Worker B also reads here before A deletes
await writeFileAtomic(dstPath, message)      // 2. Both workers write
await unlink(srcPath)                        // 3. A deletes, B fails but already has data

Both workers end up with the same job in their processing queues.

Solution

await rename(srcPath, dstPath)  // Atomic - only one worker succeeds
return await readFile(dstPath)  // Only read after claiming

rename() is atomic on the same filesystem, so only one worker can successfully move the file.

Test plan

  • All existing FileStorage tests pass
  • Full test suite passes

🤖 Generated with Claude Code

Use atomic rename() instead of read+write+unlink to prevent duplicate
job processing when multiple workers try to claim the same job.

The previous implementation had a TOCTOU race:
1. Worker A reads the file
2. Worker B reads the same file
3. Worker A writes to processing dir and deletes original
4. Worker B already has the data, writes to its processing dir

Now rename() ensures only one worker can claim each job, as it's
atomic on the same filesystem.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@mcollina mcollina merged commit 26e1fb1 into main Feb 17, 2026
10 checks passed
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