Ruby IO#flock retry boundaries for duplicate write prevention
0 reputation · 24 Apr 2022, 10:45 UTC
When multiple Ruby processes append records to a shared file, an exclusive File::LOCK_EX via IO#flock serializes access, but it does not make the guarded write itself atomic or idempotent. If a write raises an IOError or the process is interrupted after a partial write, a naive retry inside the same locked block can duplicate bytes. The lock is advisory and is released automatically when the descriptor closes or is garbage-collected, so the retry window must be carefully bounded.
On POSIX systems, attempting to flock a file already locked by the same process raises EDEADLK, which complicates retry loops that re-acquire the lock rather than reusing the existing descriptor. Using File::LOCK_NB returns false immediately instead of blocking, but that only changes scheduling, not write durability.
Given these constraints, what is the reliable boundary for retrying a failed write under an exclusive flock without duplicating data? How should partial-write state be tracked across retries in the same process, and is re-entrant locking ever a safe pattern for this?