Add exact native mutation batch partitioning - #37
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add a handle-bound logical mutation API for Harper's derived-index adapter. A caller can submit one logical batch, have the wrapper partition it into native-size frames, and publish only after every frame is accepted. Partial native application latches the handle until rollback, preventing a later publication from exposing half a logical batch.
The change also adds read-only option validation, index-scoped retired-tree reclamation, explicit active-versus-incomplete errors, and benchmark coverage for the logical and low-level mutation drivers. The package continues to expose only Tantivy's native storage.
This advances Implement mutation batching, commit publication, reader reload, and status.
Design
ts/native.tsowns the logical-batch state machine. It snapshots caller-owned IDs before awaiting, partitions and applies frames sequentially, validates native mutation counts, batches replacement deletes, and distinguishes retryableE_BATCH_ACTIVEfrom rollback-requiredE_BATCH_INCOMPLETE.apply()rechecks the latch after typed-array coercion, whilereload()participates in the same writer fence.ts/codec.tsimplements bounded frame encoding, consumed-prefix accounting, duplicate-ID validation, and record-local rejection reporting. Oversized strings and IDs are rejected before allocation, and chunk coalescing bounds writer metadata for dense multi-value records.ts/native.tsretired-tree reclamation validates hints even when the retirement root is absent, refuses a symlinked root, confines deletion to the requested basename, and does not broaden scope through a symlinked live path.ts/native.tsopen validation and close handling normalize malformed options, preserve closed-handle diagnostics after cleanup failures, and expose quiesced cleanup failure through{ cleanupError }.ts/errors.tsandsrc/error.rskeep the new active/incomplete error codes in cross-language parity.src/lib.rs,ts/addon.d.ts, andts/load-addon.tsbump native ABI compatibility to 5 and expose the commit-payload runtime limit with a capability gate.src/native.rsadds stateless native option validation and keeps retirement naming aligned with the caller's source basename.src/protocol.rsrejects frame limits that cannot hold one minimal mutation.Developer surface
README.mddocuments logical mutation batches, rejection policy, latch recovery, validation, retirement cleanup, and benchmark usage.docs/native-backend-implementation.mdrecords the wrapper/native ownership boundary and mutation flow.docs/native-reset-quiescence.mddefines reset results, same-path reclamation, collision-safe names, and cleanup ownership.benchmarks/native.mjsaddslogicalversuslow-levelmutation drivers and logical-batch latency percentiles.package.jsonruns both drivers in benchmark smoke CI.Decisions for the human reviewer
E_INVALID_ARGUMENTandE_BATCH_TOO_LARGEfailures may become replacement deletes only when the caller opts intorejectedUpsert: "delete". Schema mismatch always fails the whole call to avoid mass deletion under configuration drift.assumeDistinctIds: trueis a trusted hot-path escape hatch. Duplicate IDs under that option are outside the API contract.pathvalue must be used for reset and reclaim.ts/native.ts, and recursive deletion scope inreclaimRetiredNativeFullTextIndexes().Verification
npm run lint— TypeScript and Clippy passed.npm test— 31 Rust tests, 99 primary Node tests, 3 worker tests, and 1 packed-package test passed.npm run benchmark:smoke— both logical and low-level mutation drivers completed. On this local smoke workload they produced about 4.4k and 4.5k durable documents/second respectively; these are sanity results, not release benchmarks.cargo fmt --checkpassed.test/native-index.test.mjscovers multi-frame application, visibility and reopen, reentrancy, overload, record snapshots, replacement-delete batching, size bounds, and reclamation scope against the real addon.test/native.test.mjscovers runtime capabilities and closed-handle behavior after injected cleanup failure.test/error-codes.test.mjspins Rust/TypeScript limits and error-code parity.test/native-admission.test.mjsandtest/native-publication.test.mjsconsume the runtime-provided payload limit rather than duplicating it.Complexity: high — public mutation semantics, durable-state recovery, native ABI capability checks, and recursive cleanup boundaries.
Comment generated by kAIle (GPT-5)
Review-Coverage: authored=codex; ran=cursor-composer,claude,cursor-grok; adjudicated=domain; blocked=gemini(auth); rounds=18; full=5 @ 522d38b
Human-Review-Need: 4 @ 522d38b