brainy/tests/integration
David Snelling 550bd4a19c fix: saveBinaryBlob unique tmp suffix + ENOENT swallow on rename
FileSystemStorage.saveBinaryBlob used a bare ${filePath}.tmp suffix for its
atomic-write temp file. Two concurrent same-key calls computed the SAME temp
path; both writeFile'd, the first rename succeeded, the second rename fired
against a missing temp and threw ENOENT. The throw propagated up through
brain.flush() and broke any downstream job that called it.

Reproduced in production (Brainy 7.30 + Cortex 2.7 + mmap-filesystem):

  [job-queue] gcs-backup: failed - ENOENT: no such file or directory,
    rename '/data/brainy-data/.../_column_index/owner/DELETED.bin.tmp'
         -> '/data/brainy-data/.../_column_index/owner/DELETED.bin'

The race was two cron jobs (gcs-backup hourly + flush-brain every 15min) both
calling flush(), triggering column-store compaction over the same fields,
overlapping at the rename. Off-site backups had been failing continuously for
~48 hours.

PATCH

src/storage/adapters/fileSystemStorage.ts:992-999 — saveBinaryBlob now uses a
unique per-writer temp suffix matching the pattern at every other atomic-write
site in the same file (lines 336, 551, 744, 781, 1529, 2908):

  const tmpPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`

Adds defensive ENOENT swallow on rename: if the temp is gone, the work has
already landed (saveBinaryBlob is idempotent for a given key — all callers
persist the same logical bytes per key). Cleans up the temp on any other
rename failure to avoid orphan .tmp.* files.

SCOPE AUDIT

One bug site. Audit results:

- FileSystemStorage: six sibling atomic-write sites already used unique
  suffixes (lines 336/551/744/781/1529/2908); only saveBinaryBlob was the
  outlier. All six rechecked. Clean.
- OPFSStorage: WritableStream (no tmp+rename). Not affected.
- GCSStorage / R2Storage / AzureBlobStorage / S3CompatibleStorage: object-store
  PUT (atomic at the API). Not affected.
- MemoryStorage: in-memory. Not affected.
- HistoricalStorageAdapter: read-only. Not affected.
- COW / versioning / snapshot / HNSW / aggregation: all delegate to storage
  adapters via saveBinaryBlob / writeObjectToPath. They get the fix
  automatically by using the patched primitive.

The bare-`.tmp` pattern is now gone repo-wide.

BENEFICIARIES

Beyond the reported column-store-compaction race:

- HNSW connection persistence (src/hnsw/hnswIndex.ts:252 → saveBinaryBlob)
  was structurally susceptible to the same race. No production reports of
  HNSW failures (probably because HNSW writes are more naturally serialized
  by the index lock), but the fix removes the latent issue.
- Any future caller of saveBinaryBlob inherits the safer semantics.

TESTS

New tests/integration/savebinaryblob-concurrent-rename.test.ts (4 tests):
- 20 concurrent saveBinaryBlob(sameKey, ...) all resolve without throwing
- No orphan .tmp.* siblings remain in the blob directory afterwards
- Production-shape: two concurrent compactor passes over 10 column-index
  fields (owner, path, permissions, vfsType, modified, createdAt, accessed,
  updatedAt, mimeType, size). All 20 calls succeed; each field ends with
  valid bytes.
- Single-writer path still produces correct bytes (no regression on common
  case).

Verified the first three tests reproduce the production ENOENT error
verbatim on the pre-7.31.1 code path (stashed the fix, watched them fail
with the exact production error).

VERIFICATION

- npx tsc --noEmit: clean
- npm test: 1468 / 1468 unit
- New integration suite: 4/4
- npm run build: clean

CORTEX COMPATIBILITY

Zero changes. The Cortex mmap-filesystem adapter wraps FileSystemStorage
and inherits the patch automatically.

FORWARD-COMPAT

8.0's Db.persist() will route through the same patched primitive; no
additional work needed when the immutable Db API ships.
2026-06-09 10:36:02 -07:00
..
advanced-apis-regression.test.ts feat: array-unnest groupBy for aggregates + batch-embed entity extraction 2026-05-26 14:20:40 -07:00
aggregation.test.ts feat: add aggregation engine with incremental SUM/COUNT/AVG/MIN/MAX, GROUP BY, and time windows 2026-02-16 16:57:53 -08:00
all-apis-comprehensive.test.ts fix: update tests for v5.1.0 API changes (VFS auto-init + property access) 2025-11-02 11:38:12 -08:00
api-parameter-validation.test.ts feat: Stage 3 CANONICAL taxonomy with 169 types (v5.5.0) 2025-11-06 09:02:23 -08:00
azure-storage.test.ts chore(release): 4.0.0 2025-10-17 14:48:34 -07:00
batchImportWithRelations.test.ts fix: resolve REAL v5.7.x race condition - type cache layer (v5.7.3) 2025-11-12 12:13:35 -08:00
brainy-complete.integration.test.ts fix: resolve 10 test failures across clustering, metadata, and deletion 2025-10-09 16:33:08 -07:00
brainy-core.integration.test.ts feat: Brainy 3.0 - Production-ready Triple Intelligence database 2025-09-11 16:23:32 -07:00
brainy-phase1c-integration.test.ts feat: Stage 3 CANONICAL taxonomy with 169 types (v5.5.0) 2025-11-06 09:02:23 -08:00
bun-compile-test.ts feat: replace transformers.js with direct ONNX WASM for Bun compatibility 2025-12-17 17:42:37 -08:00
clear-persistence.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
clear-vfs.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
commit-ref-bug.test.ts feat: add entity versioning system with critical bug fixes (v5.3.0) 2025-11-04 11:19:02 -08:00
commit-state-capture.test.ts fix: commit() now flushes and captures state by default 2026-03-23 15:45:46 -07:00
cortex-compat.test.ts fix: find()/stats() correctness + Cortex compat (BR-FIND-WHERE-ZERO, BR-DEFENSIVE-INTERFACE) 2026-05-15 12:31:28 -07:00
count-synchronization.test.ts feat: Stage 3 CANONICAL taxonomy with 169 types (v5.5.0) 2025-11-06 09:02:23 -08:00
cow-commit-storage.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
cow-full-integration.test.ts test: fix COW tests and add comprehensive metadata-only integration test 2025-11-18 16:06:34 -08:00
empty-tree-bug.test.ts fix: create proper initial commit instead of using tree hash for main branch 2025-11-04 13:34:51 -08:00
entity-confidence-weight.test.ts fix: update tests for v5.1.0 API changes (VFS auto-init + property access) 2025-11-02 11:38:12 -08:00
find-limits.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
find-unified-integration.test.ts fix: resolve 10 test failures across clustering, metadata, and deletion 2025-10-09 16:33:08 -07:00
find-where-zero.test.ts fix: find()/stats() correctness + Cortex compat (BR-FIND-WHERE-ZERO, BR-DEFENSIVE-INTERFACE) 2026-05-15 12:31:28 -07:00
fork-persistence.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
gcs-native-storage.test.ts feat: simplify GCS storage naming and add Cloud Run deployment options 2025-10-20 11:12:32 -07:00
gcs-persistence-fix.test.ts fix: implement unified UUID-based sharding for metadata across all storage adapters 2025-10-08 13:26:35 -07:00
get-relations-fix.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
history-ref-resolution-bug.test.ts fix: resolve critical COW ref resolution and versioning bugs 2025-11-04 13:05:59 -08:00
hnsw-rebuild.test.ts fix: correct test assertions for addMany return value and use valid VerbType 2025-10-10 14:23:24 -07:00
hybrid-search-cow.test.ts feat: add match visibility and semantic highlighting to hybrid search 2026-01-26 17:16:18 -08:00
initial-commit-null-parent.test.ts fix: add NULL hash guards to prevent v5.3.3 regression 2025-11-04 15:39:58 -08:00
memory-enhancements-v5.11.0.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
metadata-only-comprehensive.test.ts test: fix COW tests and add comprehensive metadata-only integration test 2025-11-18 16:06:34 -08:00
metadata-vector-exclusion.test.ts fix: v3.50.2 emergency hotfix - exclude numeric field names from metadata indexing 2025-10-16 16:31:06 -07:00
migration.test.ts feat: add migration system with error handling, validation, and enterprise hardening 2026-02-09 16:13:14 -08:00
multi-process-safety.test.ts fix: find()/stats() correctness + Cortex compat (BR-FIND-WHERE-ZERO, BR-DEFENSIVE-INTERFACE) 2026-05-15 12:31:28 -07:00
orderby-sort-bug.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
phase3TypeFirstQuery.integration.test.ts feat: Phase 3 - Unified Semantic Type Inference (Nouns + Verbs) 2025-10-16 10:59:26 -07:00
readAfterWrite.test.ts fix: resolve v5.7.x race condition with write-through cache (v5.7.2) 2025-11-12 09:32:52 -08:00
relationship-intelligence.test.ts fix: createEntities defaults to true, enable AI features by default 2025-10-23 16:54:40 -07:00
remaining-apis.test.ts fix: update tests for v5.1.0 API changes (VFS auto-init + property access) 2025-11-02 11:38:12 -08:00
rev-and-ifabsent.test.ts feat: per-entity _rev + update({ ifRev }) CAS + add({ ifAbsent }) 2026-06-09 10:04:24 -07:00
s3-storage.test.ts feat: Brainy 3.0 - Production-ready Triple Intelligence database 2025-09-11 16:23:32 -07:00
savebinaryblob-concurrent-rename.test.ts fix: saveBinaryBlob unique tmp suffix + ENOENT swallow on rename 2026-06-09 10:36:02 -07:00
smart-import.test.ts feat: implement progressive flush intervals for streaming imports 2025-10-22 17:36:27 -07:00
storage-batch-operations.test.ts feat: add storage-level batch operations to eliminate N+1 query patterns 2025-11-19 08:59:11 -08:00
strict-mode-self-test.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
subtype-and-facets.test.ts feat: subtype top-level field + trackField + migrateField 2026-06-04 17:25:28 -07:00
typeAwareHNSW.integration.test.ts feat: Phase 2 Type-Aware HNSW - 87% memory reduction @ billion scale 2025-10-15 15:39:28 -07:00
update-asymmetry.test.ts fix: update() field asymmetry causing index corruption 2026-01-26 12:12:11 -08:00
verb-subtype-and-enforcement.test.ts feat: verb subtype + updateRelation + requireSubtype enforcement 2026-06-05 11:15:52 -07:00
versioning.test.ts fix(versioning): clean architecture with index pollution prevention 2025-12-09 09:36:10 -08:00
vfs-and-graph-entities.test.ts fix: update tests for v5.1.0 API changes (VFS auto-init + property access) 2025-11-02 11:38:12 -08:00
vfs-api-wiring.test.ts fix: update tests for v5.1.0 API changes (VFS auto-init + property access) 2025-11-02 11:38:12 -08:00
vfs-debug.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
vfs-historical-reads.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
vfs-import-verification.test.ts fix: recalibrate find({ limit }) cap + two-tier enforcement + caller location 2026-06-08 12:49:43 -07:00
vfs-knowledge-separation.test.ts fix: update tests for v5.1.0 API changes (VFS auto-init + property access) 2025-11-02 11:38:12 -08:00
vfs-performance-v5.11.1.test.ts fix: adjust VFS performance test expectations to realistic values 2025-11-18 16:19:37 -08:00
vfs-versioning.test.ts fix(versioning): VFS file versions now capture actual blob content 2025-12-09 16:13:45 -08:00
wasm-embeddings.test.ts feat: migrate embeddings to Candle WASM + remove semantic type inference 2026-01-06 12:52:34 -08:00