brainy/tests/unit/metadata-cold-read-guard.test.ts

90 lines
3.4 KiB
TypeScript
Raw Normal View History

/**
* Metadata cold-read guard (verifyMetadataLive) 7.33.5 hotfix.
*
* A downstream deployment reported cold `find({ where })` returning a silent `[]`
* on a freshly-opened brain (a native metadata index that reports data but has
* not loaded its field postings), blanking filtered pages after every restart.
* This guard, the field-index counterpart of verifyGraphAdjacencyLive (7.33.4),
* probes a known persisted value on the first filtered find(): if the index does
* not serve it, brainy rebuilds and re-probes, and raises a loud
* MetadataIndexNotReadyError only if the rebuild still can't serve never a
* silent empty result that misrepresents existing data.
*
* The JS index cold-loads correctly, so we simulate the cold native failure mode
* by intercepting the provider's getIdsForFilter/rebuild.
*/
import { describe, it, expect, beforeEach } from 'vitest'
import { Brainy, NounType, MetadataIndexNotReadyError } from '../../src/index.js'
const V = () => Array.from({ length: 384 }, (_, i) => Math.sin(i * 0.1) + 0.001)
describe('Metadata cold-read guard (7.33.5)', () => {
let brain: any
beforeEach(async () => {
brain = new Brainy({ requireSubtype: false, storage: { type: 'memory' } })
await brain.init()
await brain.add({ vector: V(), type: NounType.Concept, metadata: { status: 'active' } })
await brain.add({ vector: V(), type: NounType.Concept, metadata: { status: 'archived' } })
await brain.flush()
})
it('warm brain: filtered find is correct and the guard does not rebuild', async () => {
const mi = brain.metadataIndex
let rebuilds = 0
const origRebuild = mi.rebuild.bind(mi)
mi.rebuild = async () => {
rebuilds++
return origRebuild()
}
const res = await brain.find({ where: { status: 'active' }, limit: 100 })
expect(res.length).toBe(1)
expect(rebuilds).toBe(0)
expect(brain._metadataVerified).toBe(true)
mi.rebuild = origRebuild
})
it('cold index: verifyMetadataLive self-heals via rebuild — find({where}) is correct, NOT silent []', async () => {
const mi = brain.metadataIndex
const origGetIds = mi.getIdsForFilter.bind(mi)
const origRebuild = mi.rebuild.bind(mi)
let cold = true
brain._metadataVerified = false
mi.getIdsForFilter = async (...a: any[]) => (cold ? [] : origGetIds(...a))
mi.rebuild = async () => {
await origRebuild()
cold = false
}
try {
const res = await brain.find({ where: { status: 'active' }, limit: 100 })
expect(res.length).toBe(1)
} finally {
mi.getIdsForFilter = origGetIds
mi.rebuild = origRebuild
}
})
it('unrecoverably cold index: find({where}) throws MetadataIndexNotReadyError — never a silent []', async () => {
const mi = brain.metadataIndex
const origGetIds = mi.getIdsForFilter.bind(mi)
const origRebuild = mi.rebuild.bind(mi)
brain._metadataVerified = false
mi.getIdsForFilter = async () => []
mi.rebuild = async () => {}
try {
await expect(brain.find({ where: { status: 'active' }, limit: 100 })).rejects.toBeInstanceOf(
MetadataIndexNotReadyError
)
} finally {
mi.getIdsForFilter = origGetIds
mi.rebuild = origRebuild
}
})
it('a query with no filter does not trigger the metadata probe', async () => {
brain._metadataVerified = false
await brain.find({ vector: V(), limit: 5 })
expect(brain._metadataVerified).toBe(false)
})
})