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
22
RELEASES.md
22
RELEASES.md
|
|
@ -10,6 +10,28 @@ Full auto-generated changelog: `CHANGELOG.md` · Releases: https://github.com/so
|
|||
|
||||
---
|
||||
|
||||
## v8.8.1 — 2026-07-18 (the import dedup off-switch is now honest + lifecycle-safe)
|
||||
|
||||
The post-import background deduplication pass (a merge-DELETE writer that runs ~5 minutes
|
||||
after an import, merging entities judged duplicates by id / name / vector similarity) had
|
||||
three lifecycle defects, all fixed:
|
||||
|
||||
- **`enableDeduplication: false` now actually disables it.** The background pass was
|
||||
scheduled unconditionally — an import that explicitly opted out could still have
|
||||
entities auto-removed 5 minutes later. The flag now gates BOTH the inline merge and
|
||||
the background pass (regression-pinned).
|
||||
- **One deduplicator per brain, owned by the brain.** Each `import()` call constructed its
|
||||
own coordinator + deduplicator, so the "debounced" timer never actually debounced across
|
||||
imports (N imports = N delete timers). The brain now owns a single instance — the
|
||||
debounce genuinely spans imports — and `close()` cancels pending work, so a delete pass
|
||||
can never fire against a closed brain.
|
||||
- **The 5-minute timer is unref'd** — a pending pass no longer holds the process open
|
||||
(the exit-hang class; this timer had escaped the earlier sweep).
|
||||
|
||||
Retention note for keep-everything deployments: with `enableDeduplication: false` on
|
||||
import calls and `retention: 'all'` in config, no engine path removes records
|
||||
automatically.
|
||||
|
||||
## v8.8.0 — 2026-07-17 (OS-limit detection for pool-scale deployments)
|
||||
|
||||
Small minor: brains now detect the two OS limits that bite at pool scale and warn **before**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue