mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-08-26 08:52:59 +00:00
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.
22 lines
1.1 KiB
TypeScript
22 lines
1.1 KiB
TypeScript
import { writeFile } from 'fs/promises'
|
|
import { join } from 'path'
|
|
|
|
import { acquireCacheRefreshLock } from '../../src/cache-refresh-lock.js'
|
|
|
|
// A plain owner in its own process. It records its outcome, its token, and the
|
|
// result of the publication fence into the barrier directory so the parent can
|
|
// assert what the owner itself believed while a contender was racing it.
|
|
const [cacheDir, barrierDir, holdMs, heartbeatMs = '200'] = process.argv.slice(2)
|
|
if (!cacheDir || !barrierDir || !holdMs) throw new Error('missing owner argument')
|
|
|
|
const refresh = await acquireCacheRefreshLock({ cacheDir, heartbeatMs: Number(heartbeatMs) })
|
|
if (refresh.outcome !== 'acquired') {
|
|
await writeFile(join(barrierDir, `owner.${refresh.outcome}`), '')
|
|
process.exit(0)
|
|
}
|
|
await writeFile(join(barrierDir, 'owner.acquired'), refresh.handle.token)
|
|
await new Promise(resolve => { setTimeout(resolve, Number(holdMs)) })
|
|
// The publication fence, exactly as parser.ts uses it before saving.
|
|
await writeFile(join(barrierDir, `owner.verify.${await refresh.handle.verifyStillOwner()}`), '')
|
|
await refresh.handle.release()
|
|
await writeFile(join(barrierDir, 'owner.done'), '')
|