[NIDX-02C] Cut the Property database over to the native writer
- Dominant language
- Java
- Stars
- 25k
- Forks
- 6.6k
- Avg merge
- 10h 5m
- Merged PRs (30d)
- 16
Description
Parent: #14007
Blocked by: #14074 (NIDX-02B), or by #14073 directly if 02B is folded in here.
This is the leaf that puts native bytes under a live Property writer. It is deliberately last and deliberately small: by the time it starts, the encoder is proven against two independent readers (#14073) and the plugin contract is proven against the lifecycle manager (#14074), so the diff here is registration plus selection plus rollback.
## Boundary
1. Register the native plugin in `inverted.NewStore`'s configuration.
2. Resolve **one Property-database-wide** implementation selection at startup, before scanning the directory or opening any shard store, and have `banyand/property/db/shard.go:newShard` use that selection for every existing and newly created shard. Today that line unconditionally calls `inverted.NewStore`.
3. Establish exclusive writer ownership before either implementation opens a shard writer; a process that cannot establish ownership fails rather than proceeding.
4. Implement rollback: stop admission, drain durable callbacks, close every active shard writer, change the selection, reopen the same files with the retained legacy constructor.
## Constraints carried from the workstream
- Selection is Property-database-wide, never inferred per shard, and never inferred from ICE segments, snapshot manifests, CRC32 values, or other writer-origin heuristics.
- No index-local PID file, lock file, or writer-origin marker. Such runtime files are outside ICE/snapshot compatibility.
- Simultaneous native and legacy writers for the Property database are prohibited.
- Legacy-created shards open without rewrite and retain documents, repeated stored values, deletions, and explicit order.
- The retained legacy constructor is an explicit rollback choice during the compatibility window, not a second active writer.
## The dependency-policy gate — resolve before implementation
Registration is the one line in the whole NIDX-02 ladder that cannot avoid naming the retired dependency: the plugin is registered through the aliased index package, and that selector carries the token the lexical gate forbids in added lines. Every other leaf is reachable without it.
**This must be settled before the first commit**, as an explicit decision recorded in the PR description: either a narrow, pre-approved exemption for the registration call site, or a neutral bridge that exposes registration without the token. Do not begin implementation with this open, and do not widen the exemption beyond the single call site.
## RED / E2E / suites
To be sharpened when this becomes the oldest unblocked leaf. The RED anchors on `newShard` selecting the native implementation for a legacy-created shard; the e2e on update → durable callback → close/reopen → exact query and ordered result, plus a rollback cycle reopening the same files with the legacy constructor.
## Non-scope
Merge, expiry, GC, backup, repair integration, range and boolean query, and explicit sort beyond what Property's current callers already exercise. Those follow once the writer is live.
Contributor guide
Research direction
Resolve the dependency-policy gate before implementation, then inspect inverted.NewStore configuration and banyand/property/db/shard.go:newShard. Verify the RED and end-to-end scenarios described in the issue: native selection for legacy-created shards, durable update and reopen behavior, exact ordered results, and rollback reopening the same files with the legacy constructor.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100