Generated design docs and implementation plans via Codex for: - Batch 13: FileStore Read/Query - Batch 14: FileStore Write/Lifecycle - Batch 15: MsgBlock + ConsumerFileStore - Batch 18: Server Core - Batch 19: Accounts Core - Batch 20: Accounts Resolvers - Batch 21: Events + MsgTrace - Batch 22: Monitoring All plans include mandatory verification protocol and anti-stub guardrails. Updated batches.md with file paths and planned status.
5.3 KiB
Batch 13 FileStore Read/Query Design
Context
- Batch:
13(FileStore Read/Query) - Dependency: Batch
12(FileStore Recovery) - Scope: 8 feature IDs, 0 mapped tests
- Go reference:
golang/nats-server/server/filestore.go(primarily lines3241-3571) - .NET target:
dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs
Features in scope:
1006fileStore.checkSkipFirstBlock1007fileStore.checkSkipFirstBlockMulti1008fileStore.selectSkipFirstBlock1009fileStore.numFilteredPending1010fileStore.numFilteredPendingNoLast1011fileStore.numFilteredPendingWithLast1014fileStore.allLastSeqsLocked1015fileStore.filterIsAll
Problem Statement
JetStreamFileStore currently delegates nearly all query behavior to JetStreamMemStore. Batch 13 requires file-store-native read/query helpers that depend on file-store indexes (_psim, _bim, _blks) and file-store locking patterns. Without these helpers, later file-store read/write batches cannot safely switch from delegation to true file-backed query paths.
Approaches Considered
Approach 1 (Recommended): Implement file-store-native helpers now, keep public delegation stable
Implement the 8 methods in JetStreamFileStore as internal/private helpers that operate on _psim, _bim, _blks, and MessageBlock metadata. Keep the current public IStreamStore delegation unchanged for now, but add focused tests for helper correctness and edge cases.
Pros:
- Preserves current behavior while enabling later batches.
- Aligns tightly with Go logic and lock semantics.
- Reduces risk when moving public query paths to file-store-native execution.
Cons:
- Adds methods that are not yet fully wired into every public API path.
- Requires test harness/setup for internal state.
Approach 2: Keep delegation and defer helper implementation to Batch 14+
Do nothing in Batch 13 besides documentation/notes, then implement all helpers when public read paths are ported.
Pros:
- Lower immediate implementation effort.
Cons:
- Violates the intent of Batch 13 feature scope.
- Pushes complexity/risk into later larger batches.
- Prevents granular verification of these helpers.
Approach 3: Replace delegation immediately and port full read/query path end-to-end
Implement helpers plus rewire all relevant public methods (NumPending, MultiLastSeqs, etc.) to native file-store logic in this batch.
Pros:
- End-state behavior reached sooner.
Cons:
- Scope explosion beyond 8 Batch 13 features.
- High regression risk and poor fit for dependency sequencing.
Recommended Design
1) FileStore helper surface for Batch 13
Add/port the following methods in JetStreamFileStore with Go-equivalent behavior:
CheckSkipFirstBlock(string filter, bool wc, int bi)CheckSkipFirstBlockMulti(SimpleSublist sl, int bi)SelectSkipFirstBlock(int bi, uint start, uint stop)NumFilteredPending(string filter, ref SimpleState ss)NumFilteredPendingNoLast(string filter, ref SimpleState ss)NumFilteredPendingWithLast(string filter, bool includeLast, ref SimpleState ss)AllLastSeqsLocked()FilterIsAll(string[] filters)
2) State and indexing model
- Use
_psim(SubjectTree<Psi>) for per-subject totals and first/last block index hints. - Use
_bimto dereference block index (uint) toMessageBlock. - Use
_blksordering for forward/backward block scans. - Preserve lazy correction behavior for stale
Psi.Fblkwhen first-sequence lookup misses.
3) Locking and concurrency model
- Methods ending with
Lockedassume_muread lock is held by caller. - Avoid lock upgrade from read to write in-place.
- For stale
Fblkcorrection, schedule deferred write-lock update (Go uses goroutine). In C#, use a backgroundTask.Runthat reacquires_muwrite lock and revalidates before update. - Avoid nested read-lock recursion patterns that can deadlock with pending writes.
4) Error and boundary behavior
- Return
StoreErrors.ErrStoreEOFwhen skip/jump helpers find no matching future blocks. - Return empty results (not exceptions) when there are no matching subjects for filtered pending.
- Keep null checks defensive for
_psim,_bim, missing blocks, and empty_blks.
5) Testing strategy
- Add focused tests for helper behavior in
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreReadQueryTests.cs. - Derive cases from Go tests around:
TestFileStoreFilteredPendingPSIMFirstBlockUpdateTestFileStoreWildcardFilteredPendingPSIMFirstBlockUpdateTestFileStoreFilteredPendingPSIMFirstBlockUpdateNextBlockTestJetStreamStoreFilterIsAll
- Run existing related tests (
JetStreamFileStoreTests,StorageEngineTestssubset,JetStreamMemoryStoreTestssubset) as regression gates.
Non-Goals
- Full migration of public file-store query APIs away from
_memStoredelegation. - Implementing unrelated file-store write/lifecycle features from Batch 14.
- Porting new PortTracker-mapped test IDs (Batch 13 has 0 mapped tests).
Acceptance Criteria
- All 8 feature methods are implemented with behavior aligned to Go intent.
- No placeholder/stub patterns in touched source/tests.
dotnet build dotnet/passes after each feature group.- Related test gates pass before features are marked
verified. - Feature status updates are evidence-backed and chunked (max 15 IDs).