codeburn/tests/fixtures/cache-refresh-slow-owner.ts
Aditya Vikram Singh d5144593f3 fix(cache): recover a corrupt session-refresh lock instead of freezing ingestion
observe() classified a stable unparseable session-refresh.lock body as the
terminal 'unavailable'. parseAllSessions routes that to a read-only parse, so a
zero-byte or truncated lock froze warm-cache ingestion permanently across every
later run while each command still exited successfully.

A corrupt body is now a recoverable observation carrying a real mtime, and is
recovered only through the UNMODIFIED staleness gate — tryTakeover and the age
check are byte-identical to main. sameObservation gains an explicit null/non-null
boundary and a sha1 of the raw bytes, because two corrupt bodies have no tokens
to compare and mtime granularity is coarse on some filesystems.

The heartbeat deliberately does NOT rewrite a body it cannot prove is its own.
An owner that cannot prove ownership ends its ownership: mtime stops advancing,
the publication fence refuses, and a successor recovers the lock one staleMs
later. Losing that parse is the price of never having two owners.
2026-07-30 13:06:25 +05:30

25 lines
1.2 KiB
TypeScript

import { pbkdf2 } from 'crypto'
import { writeFile } from 'fs/promises'
import { join } from 'path'
import { acquireCacheRefreshLock } from '../../src/cache-refresh-lock.js'
// Saturate the (size-1) libuv threadpool so every fs operation inside
// createExclusive queues behind a pbkdf2 round. No test hook and no patched
// module: this is what an ordinary process looks like mid cold parse, and it
// widens the window in which the lock exists at zero bytes -- between
// open(path,'wx') and the awaited body write -- to something observable.
const [cacheDir, barrierDir] = process.argv.slice(2)
if (!cacheDir || !barrierDir) throw new Error('missing owner argument')
let stop = false
const churn = (): void => { if (stop) return; pbkdf2('p', 's', 400_000, 32, 'sha512', () => churn()) }
churn()
const refresh = await acquireCacheRefreshLock({ cacheDir, heartbeatMs: 10_000 })
stop = true
await writeFile(join(barrierDir, `owner.${refresh.outcome}`), refresh.outcome === 'acquired' ? refresh.handle.token : '')
if (refresh.outcome === 'acquired') {
await writeFile(join(barrierDir, `owner.verify.${await refresh.handle.verifyStillOwner()}`), '')
await refresh.handle.release()
}