fix: import dedup off-switch honesty + brain-owned lifecycle for the background pass
The post-import background deduplication pass (a merge-DELETE writer, debounced ~5 minutes after import) had four lifecycle defects: - enableDeduplication: false did not gate the background schedule — an import that explicitly opted out could still have entities auto-removed minutes later. The flag now gates both the inline and background passes. - Each import() constructed its own coordinator-owned deduplicator, so the debounce never spanned imports (N imports = N delete timers). The brain now owns a single lazy instance (getBackgroundDeduplicator). - close() never cancelled pending dedup; a delete pass could fire against a closed brain. close() now cancels it first. - The 5-minute timer held the process open (exit-hang class); now unref'd. Four regression tests pin the contract (background-dedup-lifecycle); import guides document that false disables both passes.
This commit is contained in:
parent
120205b69c
commit
4fcef7b8ed
7 changed files with 179 additions and 10 deletions
|
|
@ -10128,6 +10128,30 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
return await coordinator.import(source as Buffer | string | object, options)
|
||||
}
|
||||
|
||||
/** Brain-owned background deduplicator (lazy; see getBackgroundDeduplicator). */
|
||||
private _backgroundDedup?: import('./import/BackgroundDeduplicator.js').BackgroundDeduplicator
|
||||
|
||||
/**
|
||||
* The single brain-owned BackgroundDeduplicator, lazily constructed.
|
||||
*
|
||||
* Ownership matters here: the post-import dedup timer must outlive the
|
||||
* per-call ImportCoordinator but never the brain. One instance per brain
|
||||
* restores the intended cross-import debounce (per-coordinator instances
|
||||
* each armed their own timer, so the "debounce" never spanned imports) and
|
||||
* gives close() a handle to cancel pending work — a delete pass must never
|
||||
* fire against a closed brain.
|
||||
* @internal
|
||||
*/
|
||||
async getBackgroundDeduplicator(): Promise<
|
||||
import('./import/BackgroundDeduplicator.js').BackgroundDeduplicator
|
||||
> {
|
||||
if (!this._backgroundDedup) {
|
||||
const { BackgroundDeduplicator } = await import('./import/BackgroundDeduplicator.js')
|
||||
this._backgroundDedup = new BackgroundDeduplicator(this)
|
||||
}
|
||||
return this._backgroundDedup
|
||||
}
|
||||
|
||||
/**
|
||||
* Virtual File System API - Knowledge Operating System
|
||||
*
|
||||
|
|
@ -16070,6 +16094,10 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
|||
* This ensures deferred persistence mode data is saved
|
||||
*/
|
||||
async close(): Promise<void> {
|
||||
// Cancel any pending post-import background deduplication FIRST — it is a
|
||||
// writer (merge-deletes), and no delete pass may start mid- or post-close.
|
||||
this._backgroundDedup?.cancelPending()
|
||||
|
||||
// Change-feed teardown: no events are delivered for or after close().
|
||||
this._changeFeed.close()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue