bug-report test: document not found after cleanup() + re-insert of the same primary key - #8948
bug-report test: document not found after cleanup() + re-insert of the same primary key#8948kilbot wants to merge 1 commit into
Conversation
…nsert of the same primary key
|
Traced it further, in case it saves you time: the DocumentCache's anti-downgrade guard (the out-of-order protection from #8609 in doc-cache.ts) rejects the re-inserted document because its revision chain restarts at height 1, which is "older" than the cached tombstone's height 2 — and cleanup emits no events, so the cache never learns the tombstone was purged. That's why findOne(pk) (which reads through the cache) returns null while a selector-less find() and count() are correct. Evicting deleted-latest entries from cacheItemByDocId after a cleanup pass fixes this test on memory and dexie, with cleanup/rx-query/rx-collection/event-reduce/doc-cache/reactive/rx-document suites staying green. One caveat: under multiInstance only the instance that ran the cleanup evicts its own cache. Happy to push that as a commit here if you want it — otherwise the failing test stands on its own. |
The census lifecycle cycled insert -> claim -> remove -> re-insert of the same queryKey every ~15 minutes. Re-inserting a soft-deleted primary key is the resurrection pattern that leaked index rows in the premium storage (patched at the storage layer in #1164) and still trips an unfixed rxdb-core cache bug after cleanup purges the tombstone (pubkey/rxdb#8948). Removing the delete -> re-insert cycle removes the trigger entirely and cuts write churn on the highest-churn collection. A terminal 'idle' status replaces deletion: the runner's three remove() sites become markIdle CAS transitions (same replaceIfCurrent contract as markFailed), the maintenance-lane seeder wakes idle states when their census cache entry goes stale (claimNew only for genuinely-absent keys, preserving exactly-once claims), and readRunnable naturally excludes idle. Schema bumps 2 -> 3 (enum widening changes the schema hash) with a passthrough migration. Mutation-checked: dropping the success->idle transition fails the runner + maintenance tests; dropping the v3 migration fails the schema test. Implemented by Codex from a written spec; reviewed line-by-line, suite and mutation checks re-run independently. Claude-Session: https://claude.ai/code/session_01VRdA9wbToqQXCvH1JFDBNH
Filled in the bug-report template, per its instructions.
The sequence is: insert → remove() → cleanup(0) → insert the same primary key again. The second insert succeeds, but
findOne()returns null for the document that was just written. Closing and reopening the database shows the document was stored correctly — the live instance is what's wrong. A freshfind()with a selector also misses the document whilecount()returns 1, so it isn't query-cache staleness.Fails on current master with both
DEFAULT_STORAGE=memoryandDEFAULT_STORAGE=dexie, and witheventReduce: falsetoo:While digging we noticed the conflict-retry for inserting a previously-deleted key (
reInsertsin rx-storage-helper.ts) emits its change event withpreviousDocumentData: nulleven though the write carried the tombstone asprevious— that might be a useful place to start looking. Possibly related: #7984 (bulk revival of soft-deleted docs, SQLite).Context: our production app keeps hitting a class of malformed-JSON errors in the premium OPFS storage, and delete → re-insert of the same primary key turned out to be the trigger. This test is the smallest storage-independent piece we could distill from it. The OPFS-specific side (index files growing by one row per delete → re-insert cycle) I'll file separately in rxdb-premium-issues with its own reproduction.
Finally — an apology for the earlier AI-heavy submissions here and in rxdb-premium-issues (#8841, premium PR 26). I'm honestly too busy to write these investigations up myself, so I lean on AI tooling; all I knew first-hand was that I kept getting this class of malformed-JSON bugs without knowing where they came from. I've tried to keep this one to exactly what the template asks for: a failing test.