codeburn/tests/fixtures/cache-refresh-worker.ts
iamtoruk 0bfdfa372a perf(cache): shard the session cache per provider
A warm launch rewrote the entire session cache whenever any provider
appended a few KB: on a 6 GB corpus that is a 155 MB stringify + fsync
every run. The on-disk cache is now a version-suffixed directory holding
one shard per provider plus a small envelope, and a save rewrites only
the providers marked dirty.

- Dirtiness is tracked per provider (markCacheDirty) instead of one
  global flag, so an appended Claude session no longer republishes
  Codex, Copilot and the rest.
- Shards carry a nonce in their filename and the envelope is renamed
  last, so a save is published at a single point: readers never see a
  half-updated set, and a writer that loses the refresh ownership fence
  leaves the canonical shards untouched.
- A shard that fails validation is treated as an absent provider rather
  than rejecting the whole cache, so one malformed turn costs one
  provider's re-parse instead of every provider's history.
- v7 migrates losslessly: the blob is re-laid-out into shards and
  removed only once that save publishes. Nothing re-parses.
- Cold-parse progress saves now trigger every N files parsed rather than
  every 5s, so a slow cold parse no longer rewrites the growing cache on
  a wall clock.
2026-08-16 19:03:12 -07:00

43 lines
1.8 KiB
TypeScript

import { existsSync } from 'fs'
import { mkdir, readFile, writeFile } from 'fs/promises'
import { join } from 'path'
import { acquireCacheRefreshLock } from '../../src/cache-refresh-lock.js'
import { loadCache, markCacheDirty, saveCache } from '../../src/session-cache.js'
const [cacheDir, barrierDir, id, sourcePath, bypass = 'false'] = process.argv.slice(2)
if (!cacheDir || !barrierDir || !id || !sourcePath) throw new Error('missing worker argument')
async function waitFor(name: string): Promise<void> {
const path = join(barrierDir!, name)
while (!existsSync(path)) await new Promise(resolve => { setTimeout(resolve, 5) })
}
process.env['CODEBURN_CACHE_DIR'] = cacheDir
await mkdir(barrierDir, { recursive: true })
const refresh = bypass === 'true' ? null : await acquireCacheRefreshLock({ cacheDir, waitMs: 2_000, pollMs: 5 })
if (refresh && refresh.outcome !== 'acquired') {
await writeFile(join(barrierDir, `${id}.${refresh.outcome}`), '')
process.exit(0)
}
try {
const cache = await loadCache()
// Parsing is deliberately tiny; the files and barrier make the transaction
// interleaving deterministic rather than relying on parser runtime variance.
const parsed = JSON.parse(await readFile(sourcePath, 'utf-8')) as { output: number }
cache.providers['regression'] ??= { parseVersion: 'test', envFingerprint: 'test', files: {} }
cache.providers['regression'].files[sourcePath] = {
fingerprint: { dev: 1, ino: parsed.output, mtimeMs: parsed.output, sizeBytes: parsed.output },
mcpInventory: [],
turns: [],
}
markCacheDirty(cache, 'regression')
await writeFile(join(barrierDir, `${id}.parsed`), '')
await waitFor(`${id}.save`)
const published = await saveCache(cache, refresh?.handle.verifyStillOwner)
await writeFile(join(barrierDir, `${id}.${published ? 'published' : 'fenced'}`), '')
} finally {
await refresh?.handle.release()
}