Skip to content

1.1.0

Choose a tag to compare

@fuwasegu fuwasegu released this 05 Aug 08:32
c08b792

Fixes a bug where writing a single memory could freeze the server for minutes and grow the database to hundreds of megabytes. Closes #25.

Upgrading

If your database directory is far larger than the data it holds, it was bloated by the old write path. Fixing the cause does not shrink an existing database — rebuild it once:

uvx --from git+https://github.com/fuwasegu/exocortex exocortex --mode compact

Or ask your assistant to call the new exo_compact tool. Your previous database is kept under ~/.exocortex/backups/.

The bug

exo_store_memory opened and closed a kuzu.Database for every write query, not once per write. Closing one runs a full synchronous StorageManager::checkpoint(), so a single store with five tags paid 13 checkpoints. Because MCP tools run directly on the event loop, that froze every other request — exo_ping included.

The RELATED_TO.reason corruption reported in #25 turned out to be the same bug, not a second one: every checkpoint rewrote relationship column chunks without reclaiming pages. Identical 700-relationship inserts:

on-disk size time
before 265 MiB 78.7 s
after 5.6 MiB 6.2 s

47× the disk from the same data. Once a column chunk outgrew the buffer pool, reads of it failed outright with Buffer manager exception: Unable to allocate memory!.

Results

before after
store_memory (5 tags) 1513 ms, 13 DB opens 209 ms, 1 open
store_memory (no tags) 314 ms, 3 opens 24 ms, 0 opens
link_memories 153 ms, 2 opens 12 ms, 0 opens
700 relationships 115.6 s, 280 MiB 6.9 s, 13.9 MiB
test suite 371 s 70 s

What's new

  • exo_compact / --mode compact — rebuilds a bloated database and reclaims the space. Relationship text that is already unreadable cannot be recovered; those columns are reported and rebuilt empty so the rest of the graph survives. Memory content is never dropped — compaction fails loudly rather than discarding memories.
  • exo_sleep now works in proxy mode. The server hands its database lock over before spawning the dream worker. This was previously documented as unsupported; the cause was the server holding a long-lived read-only database, which blocks writers.
  • --mode dashboard opens read-only, so the standalone dashboard shares the database instead of competing for the exclusive lock.
  • New settings: EXOCORTEX_DB_IDLE_TIMEOUT (default 5s — how long the database may sit idle before the lock is handed back) and EXOCORTEX_READ_ONLY.

Also in this release

  • mcp is now capped at <2. mcp 2.0.0 removed mcp.server.fastmcp, which made a fresh install fail to import entirely. Migration to the 2.x API is tracked in #27.
  • Fixes found by an adversarial review pass before merge: a stale connection could reopen a database the manager no longer tracked and leak its file lock; a lazy query result could be closed mid-consumption; compaction could leak the source handle and swallow a failed rollback.

Full Changelog: 1.0.1...1.1.0