fix(storage): version raw RocksDB primary writes - #2170
Conversation
There was a problem hiding this comment.
Code Review
This pull request implements versioning for raw RocksDB primary writes at the store boundary to prevent collisions between prefix-less classic records (specifically those starting with structure ID 0x42) and timestamp-prefixed records. It introduces put and putSync wrappers in PrimaryRocksDatabase that stage a monotonic version and zero-flags metadata word via stageRawPrimaryEncoding before executing the write, clearing it in a finally block. It also adds comprehensive unit tests to verify this raw-write versioning behavior. There are no review comments to address, so I have no additional feedback to provide.
| this.#cache?.delete(id); | ||
| const staged = stageRawPrimaryEncoding(this.#enc, typeof options === 'number' ? options : options?.version); | ||
| try { | ||
| return super.put(id, value, options); |
There was a problem hiding this comment.
What: put(id, value, options) declares only 3 params and forwards exactly super.put(id, value, options). Any 4th argument a caller passes is silently dropped — it's not captured by any parameter and isn't forwarded via arguments/rest-spread.
Why it matters: resources/Table.ts:1152 calls primaryStore.put(Symbol.for('id_allocation'), {...}, Date.now(), version) — a 4-arg form where the trailing version is an ifVersion optimistic-concurrency guard (lmdb-js/rocksdb-js put(key, value, version, ifVersion)). That call site isn't wrapped in transactionSync (unlike the sibling createNewAllocation path at Table.ts:1237), so ifVersion is its only protection against a lost update when two workers race on id allocation. Before this PR, PrimaryRocksDatabase didn't override put() at all, so the call reached the native 4-arg API directly. Now it silently becomes an unconditional put, reopening the race between the getEntry read at Table.ts:1143 and this write.
Suggested fix: Accept and forward a 4th parameter (e.g. ifVersion?: any) through to super.put(id, value, options, ifVersion), mirroring whatever putSync needs for the same reason.
|
One blocker found (inline): |
Summary
Closes #1762
Verification
Review
Comment generated by kAIle (GPT-5.6)