2026-08-05 16:00:39 -07:00
/ * *
* @module tests / unit / brainy / persistence - policy
* @description THE ENGINE - OWNED FLUSH CADENCE pins ( A4 ,
* SELF - ENGINE - LIFECYCLE - SPRINT , David - directed : callers NEVER call flush ( )
* in hot paths ) . The production disease : 829 caller - scheduled per - write
* flushes convoying into 45 – 66 second write walls — cadence hand - rolled a
* layer above the only layer that can see dirty state and IO pressure .
*
* Pinned here : ( 1 ) the write - count trigger fires a BACKGROUND flush without
* any caller flush ( ) ; ( 2 ) the idle trigger ; ( 3 ) ` 'manual' ` restores
* caller - owned cadence exactly ; ( 4 ) THE ACK LAW — a write acknowledges
* without awaiting any background flush , even one that never resolves .
* /
import { describe , it , expect , afterEach , vi } from 'vitest'
import { Brainy } from '../../../src/index.js'
import { NounType } from '../../../src/types/graphTypes.js'
const brains : Brainy [ ] = [ ]
async function mk ( persistence ? : {
policy ? : 'auto' | 'manual'
flushEveryWrites? : number
flushIntervalMs? : number
flushOnIdleMs? : number
} ) : Promise < Brainy > {
const b = new Brainy ( {
storage : { type : 'memory' } ,
requireSubtype : false ,
. . . ( persistence && { persistence } )
} )
await b . init ( )
brains . push ( b )
return b
}
afterEach ( async ( ) = > {
for ( const b of brains . splice ( 0 ) ) await b . close ( ) . catch ( ( ) = > { } )
vi . restoreAllMocks ( )
} )
describe ( 'persistence policy — the engine owns its flush cadence' , ( ) = > {
it ( 'write-count trigger: N committed writes fire ONE background flush, no caller flush()' , async ( ) = > {
const brain = await mk ( { flushEveryWrites : 5 , flushOnIdleMs : 60_000 , flushIntervalMs : 600_000 } )
const flushSpy = vi . spyOn ( brain , 'flush' )
for ( let i = 0 ; i < 5 ; i ++ ) {
await brain . add ( { data : ` w ${ i } ` , type : NounType . Document , metadata : { i } } )
}
await vi . waitFor ( ( ) = > expect ( flushSpy ) . toHaveBeenCalled ( ) , { timeout : 5000 } )
// Single-flight: the threshold crossing kicks exactly one.
expect ( flushSpy . mock . calls . length ) . toBe ( 1 )
} )
it ( 'idle trigger: a quiet store with dirty writes flushes itself' , async ( ) = > {
const brain = await mk ( { flushEveryWrites : 10_000 , flushIntervalMs : 600_000 , flushOnIdleMs : 60 } )
const flushSpy = vi . spyOn ( brain , 'flush' )
await brain . add ( { data : 'lone write' , type : NounType . Document , metadata : { } } )
await vi . waitFor ( ( ) = > expect ( flushSpy ) . toHaveBeenCalled ( ) , { timeout : 5000 } )
} )
2026-08-10 12:15:02 -07:00
it ( 'idle debounce under load: slow writes never fire a flush per inter-write gap' , async ( ) = > {
// The contended-disk amplifier: writes slower than the idle window make
// every gap look idle — without the spacing floor this fired a full
// flush per write (measured 15 background flushes in 100 contended adds
// on a production-shaped box). The floor (min(interval, 10× idle)) caps
// idle fires; deferred, never dropped.
const brain = await mk ( { flushEveryWrites : 10_000 , flushIntervalMs : 600_000 , flushOnIdleMs : 50 } )
const flushSpy = vi . spyOn ( brain , 'flush' )
// Six writes spaced wider than the idle window (50ms) with the whole
// span inside ~one floor window (500ms): the old behavior fires ~an
// idle flush per gap (≈6); the debounced behavior fires at most two
// (one immediate boot-window fire + one at the floor boundary).
for ( let i = 0 ; i < 6 ; i ++ ) {
await brain . add ( { data : ` slow ${ i } ` , type : NounType . Document , metadata : { } } )
await new Promise ( ( r ) = > setTimeout ( r , 70 ) )
}
expect ( flushSpy . mock . calls . length , 'no flush-per-gap amplifier' ) . toBeLessThanOrEqual ( 2 )
// Deferred, never dropped: the dirty writes still persist once the
// floor elapses on the now-quiet store.
await vi . waitFor ( ( ) = > expect ( flushSpy ) . toHaveBeenCalled ( ) , { timeout : 5000 } )
} )
2026-08-05 16:00:39 -07:00
it ( "'manual' policy: the engine NEVER flushes on its own" , async ( ) = > {
const brain = await mk ( { policy : 'manual' , flushEveryWrites : 2 , flushOnIdleMs : 30 } )
const flushSpy = vi . spyOn ( brain , 'flush' )
for ( let i = 0 ; i < 6 ; i ++ ) {
await brain . add ( { data : ` m ${ i } ` , type : NounType . Document , metadata : { i } } )
}
await new Promise ( ( r ) = > setTimeout ( r , 150 ) )
expect ( flushSpy ) . not . toHaveBeenCalled ( )
} )
it ( 'THE ACK LAW: writes acknowledge without awaiting the background flush — even a hung one' , async ( ) = > {
const brain = await mk ( { flushEveryWrites : 2 , flushOnIdleMs : 60_000 , flushIntervalMs : 600_000 } )
// A flush that NEVER resolves: if any write ack awaited it, the test
// would time out. (The engine's background flight must be fire-and-log.)
vi . spyOn ( brain , 'flush' ) . mockImplementation ( ( ) = > new Promise < void > ( ( ) = > { } ) )
for ( let i = 0 ; i < 6 ; i ++ ) {
const id = await brain . add ( { data : ` a ${ i } ` , type : NounType . Document , metadata : { i } } )
expect ( id ) . toBeTruthy ( )
}
// All six writes acked while the "flush" hangs forever.
const rows = await brain . find ( { type : NounType . Document , limit : 10 } )
expect ( rows . length ) . toBe ( 6 )
// Un-hang before afterEach close(): restore the method AND drop the
// never-resolving in-flight promise (close() awaits the flight — with a
// real flush that is correct; here it is the test's own artifact).
vi . restoreAllMocks ( )
; ( brain as unknown as { _persistBackgroundFlight : Promise < void > | null } ) . _persistBackgroundFlight =
null
} )
} )