MEASURED on a 14,056-noun / 72,679-verb production-shaped store, measured solo under an exclusive lock: the vfs-bootstrap phase cost 43,021 ms of a cold open and 52,696 ms of a WARM REOPEN. What dominates it is a migration sweep — a filtered find() over the whole store hunting for root directories created before the fixed root id existed. A store either carries such duplicates or never will, and the sweep ran on every open, forever, in the foreground. It is now caused by the store's state instead of by the open count: a durable marker under _system/ records that the sweep has run, and a store carrying it never sweeps again. A store without one sweeps in the BACKGROUND — the sweep only removes duplicate roots, nothing serves from them, and it was already declared non-critical — narrated at both ends, with whenRootSweepSettled() for anyone who needs to observe rather than race it. An adapter with no raw-object door keeps the old behaviour: correctness over cost, never a silent skip. Pins: tests/integration/vfs-root-sweep-once.test.ts — the sweep runs on the first open and never on the second or third; a sweep slowed to 4s does not delay the open.
106 lines
3.9 KiB
TypeScript
106 lines
3.9 KiB
TypeScript
/**
|
||
* @module tests/integration/vfs-root-sweep-once
|
||
* @description THE OLD-ROOT SWEEP RUNS ONCE PER STORE, NOT ONCE PER OPEN.
|
||
*
|
||
* The VFS bootstrap ran a filtered `find()` over the whole store on EVERY
|
||
* open, hunting for root directories created before the fixed root id existed
|
||
* — duplicates a store has either always had or never will. MEASURED on a
|
||
* 14,056-noun / 72,679-verb store: the phase it dominates cost 43–53 SECONDS
|
||
* of every open, warm reopens included.
|
||
*
|
||
* The law: a migration sweep is caused by the store's state, not by the clock
|
||
* or the open count. It runs behind the doors, records that it ran, and a
|
||
* store carrying that record never sweeps again.
|
||
*/
|
||
|
||
import { describe, it, expect, afterEach, vi } from 'vitest'
|
||
import { mkdtempSync, rmSync, existsSync } from 'node:fs'
|
||
import { tmpdir } from 'node:os'
|
||
import { join } from 'node:path'
|
||
import { Brainy } from '../../src/brainy.js'
|
||
import { NounType } from '../../src/types/graphTypes.js'
|
||
import { VirtualFileSystem } from '../../src/vfs/VirtualFileSystem.js'
|
||
|
||
describe('the VFS old-root sweep', () => {
|
||
const dirs: string[] = []
|
||
const brains: Brainy[] = []
|
||
|
||
afterEach(async () => {
|
||
for (const b of brains.splice(0)) {
|
||
try { await b.close() } catch { /* already closed */ }
|
||
}
|
||
for (const d of dirs.splice(0)) {
|
||
try { rmSync(d, { recursive: true, force: true }) } catch { /* ignore */ }
|
||
}
|
||
vi.restoreAllMocks()
|
||
})
|
||
|
||
async function open(dir: string): Promise<Brainy> {
|
||
const brain = new Brainy({ requireSubtype: false, storage: { type: 'filesystem', path: dir } })
|
||
brains.push(brain)
|
||
await brain.init()
|
||
return brain
|
||
}
|
||
|
||
it('sweeps on the first open, records it, and never sweeps again', async () => {
|
||
const dir = mkdtempSync(join(tmpdir(), 'brainy-root-sweep-'))
|
||
dirs.push(dir)
|
||
|
||
const sweepSpy = vi.spyOn(
|
||
VirtualFileSystem.prototype as unknown as { cleanupOldRoots: () => Promise<void> },
|
||
'cleanupOldRoots'
|
||
)
|
||
|
||
const first = await open(dir)
|
||
await (first.vfs as unknown as { whenRootSweepSettled: () => Promise<void> }).whenRootSweepSettled()
|
||
expect(sweepSpy).toHaveBeenCalledTimes(1)
|
||
// The record is durable engine plumbing under _system/, like every other marker.
|
||
expect(
|
||
existsSync(join(dir, '_system', 'vfs-root-sweep.json')) ||
|
||
existsSync(join(dir, '_system', 'vfs-root-sweep.json.gz'))
|
||
).toBe(true)
|
||
|
||
await first.add({ data: 'a row so the store is not trivially empty', type: NounType.Concept })
|
||
await first.flush()
|
||
await first.close()
|
||
brains.splice(brains.indexOf(first), 1)
|
||
|
||
sweepSpy.mockClear()
|
||
const second = await open(dir)
|
||
await (second.vfs as unknown as { whenRootSweepSettled: () => Promise<void> }).whenRootSweepSettled()
|
||
expect(sweepSpy).not.toHaveBeenCalled()
|
||
|
||
await second.close()
|
||
brains.splice(brains.indexOf(second), 1)
|
||
|
||
// ...and a third open, to prove it is the record and not a one-off.
|
||
sweepSpy.mockClear()
|
||
const third = await open(dir)
|
||
await (third.vfs as unknown as { whenRootSweepSettled: () => Promise<void> }).whenRootSweepSettled()
|
||
expect(sweepSpy).not.toHaveBeenCalled()
|
||
}, 180_000)
|
||
|
||
it('the open does not wait for the sweep', async () => {
|
||
const dir = mkdtempSync(join(tmpdir(), 'brainy-root-sweep-async-'))
|
||
dirs.push(dir)
|
||
|
||
const proto = VirtualFileSystem.prototype as unknown as Record<
|
||
string,
|
||
(...args: unknown[]) => Promise<unknown>
|
||
>
|
||
const real = proto.cleanupOldRoots
|
||
proto.cleanupOldRoots = async function slow(this: unknown, ...args: unknown[]) {
|
||
await new Promise((r) => setTimeout(r, 4_000))
|
||
return real.apply(this, args)
|
||
}
|
||
try {
|
||
const startedAt = Date.now()
|
||
const brain = await open(dir)
|
||
const openMs = Date.now() - startedAt
|
||
expect(openMs).toBeLessThan(3_000)
|
||
await (brain.vfs as unknown as { whenRootSweepSettled: () => Promise<void> }).whenRootSweepSettled()
|
||
} finally {
|
||
proto.cleanupOldRoots = real
|
||
}
|
||
}, 180_000)
|
||
})
|