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.
530 lines
17 KiB
Markdown
530 lines
17 KiB
Markdown
# Batch 13 FileStore Read/Query Implementation Plan
|
|
|
|
> **For Codex:** REQUIRED SUB-SKILL: Use `executeplan` to implement this plan task-by-task.
|
|
|
|
**Goal:** Implement and verify Batch 13 FileStore read/query helpers (`1006,1007,1008,1009,1010,1011,1014,1015`) from `filestore.go` without introducing placeholder logic.
|
|
|
|
**Architecture:** Port the helper methods into `JetStreamFileStore` with Go-equivalent lock and index behavior (`_psim`, `_bim`, `_blks`), add focused unit tests for helper-level correctness, and keep current public delegation stable until later batches wire these helpers into public query paths.
|
|
|
|
**Tech Stack:** .NET 10, C# latest, xUnit 3, Shouldly, NSubstitute, PortTracker CLI, SQLite (`porting.db`)
|
|
|
|
**Design doc:** `docs/plans/2026-02-27-batch-13-filestore-read-query-design.md`
|
|
|
|
---
|
|
|
|
## Batch Facts
|
|
|
|
- Batch ID: `13`
|
|
- Name: `FileStore Read/Query`
|
|
- Dependencies: Batch `12`
|
|
- Features: `8`
|
|
- Tests mapped in batch: `0`
|
|
- Go source: `golang/nats-server/server/filestore.go`
|
|
|
|
Feature IDs:
|
|
|
|
- Group A: `1006,1007,1008`
|
|
- Group B: `1009,1010,1011`
|
|
- Group C: `1014,1015`
|
|
|
|
---
|
|
|
|
## MANDATORY VERIFICATION PROTOCOL
|
|
|
|
> **NON-NEGOTIABLE. Every feature task must follow this protocol.**
|
|
|
|
### Per-Feature Verification Loop (REQUIRED for every feature ID)
|
|
|
|
For each feature (`1006` through `1015` in this batch):
|
|
|
|
1. Read the exact Go method body and nearby comments from `golang/nats-server/server/filestore.go`.
|
|
2. Add/adjust failing unit tests that assert the method behavior (or behavior exercised through a helper entry point).
|
|
3. Run the targeted test filter and verify it fails for the expected reason.
|
|
4. Implement minimal C# code to pass the failing test.
|
|
5. Run targeted tests again and confirm pass.
|
|
6. Run `dotnet build dotnet/` and confirm build success.
|
|
7. Add feature ID to the evidence table only if steps 1-6 are complete.
|
|
|
|
### Stub Detection Check (REQUIRED after each feature group)
|
|
|
|
Run stub scans on all files touched in the group before any status update:
|
|
|
|
```bash
|
|
grep -n -E "(NotImplementedException|TODO|PLACEHOLDER)" \
|
|
dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs \
|
|
dotnet/src/ZB.MOM.NatsNet.Server/JetStream/MessageBlock.cs \
|
|
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreReadQueryTests.cs
|
|
|
|
grep -n -E "^\s*(public|private|internal|protected).*\{\s*\}$" \
|
|
dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs \
|
|
dotnet/src/ZB.MOM.NatsNet.Server/JetStream/MessageBlock.cs \
|
|
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreReadQueryTests.cs
|
|
```
|
|
|
|
If any matches are found, fix code or defer the impacted feature. Do not mark complete/verified.
|
|
|
|
### Build Gate (REQUIRED after each feature group)
|
|
|
|
```bash
|
|
dotnet build dotnet/
|
|
```
|
|
|
|
Must pass with `0` errors before feature status changes in that group.
|
|
|
|
### Test Gate (REQUIRED before `verified`)
|
|
|
|
Run related tests after each group and before any `verified` update:
|
|
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
|
|
--filter "FullyQualifiedName~JetStreamFileStoreReadQueryTests|FullyQualifiedName~JetStreamFileStoreTests|FullyQualifiedName~StorageEngineTests.FileStoreMultiLastSeqsAndLoadLastMsgWithLazySubjectState_ShouldSucceed|FullyQualifiedName~JetStreamMemoryStoreTests.MemStoreAllLastSeqs_ShouldSucceed|FullyQualifiedName~JetStreamMemoryStoreTests.MemStoreMultiLastSeqs_ShouldSucceed"
|
|
```
|
|
|
|
All selected tests must pass. Any failure blocks `verified`.
|
|
|
|
### Status Update Protocol (REQUIRED)
|
|
|
|
- Maximum `15` IDs per `feature batch-update` call.
|
|
- Evidence required per ID: Go lines reviewed, targeted test names, pass output, build pass.
|
|
- Transition order: `deferred/not_started -> stub -> complete -> verified`.
|
|
- Never mark `verified` before both Build Gate and Test Gate pass.
|
|
- If audit disagrees, use `--override "<specific evidence>"` only with concrete reason.
|
|
|
|
Status update commands for this batch:
|
|
|
|
```bash
|
|
# Claim work
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "1006-1011,1014-1015" --set-status stub --db porting.db --execute
|
|
|
|
# Group completion (run per group with only that group's IDs)
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "<group ids>" --set-status complete --db porting.db --execute
|
|
|
|
# Group verification (after test gate)
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "<group ids>" --set-status verified --db porting.db --execute
|
|
```
|
|
|
|
### Checkpoint Protocol (REQUIRED between tasks)
|
|
|
|
Between Task 2, Task 3, and Task 4:
|
|
|
|
1. Run full build:
|
|
```bash
|
|
dotnet build dotnet/
|
|
```
|
|
2. Run full unit test project:
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
```
|
|
3. Confirm pass/fail/skip summary and capture it in notes.
|
|
4. Commit checkpoint before moving to next task.
|
|
|
|
---
|
|
|
|
## ANTI-STUB GUARDRAILS (NON-NEGOTIABLE)
|
|
|
|
These rules apply to both production features and tests in this plan.
|
|
|
|
### Forbidden Patterns
|
|
|
|
Do not leave any of these in touched code:
|
|
|
|
- `throw new NotImplementedException(...)`
|
|
- `// TODO` or `// PLACEHOLDER` in implemented method bodies
|
|
- Empty method bodies (including one-line `{ }` placeholders)
|
|
- Test methods with no assertions
|
|
- Tests that only assert non-null for complex query behavior
|
|
|
|
### Hard Limits
|
|
|
|
- Max `15` feature IDs per status batch update.
|
|
- Max `1` feature group per status-update cycle.
|
|
- Mandatory build + related test gate before `verified`.
|
|
- Mandatory checkpoint commit between feature groups.
|
|
|
|
### If You Get Stuck
|
|
|
|
If a feature cannot be completed without missing infrastructure:
|
|
|
|
1. Leave or move that feature to `deferred` (never ship a stub).
|
|
2. Record the blocker using `--override` with specific reason.
|
|
3. Continue with remaining features in the same group.
|
|
4. Do not force `complete/verified` to unblock the batch.
|
|
|
|
Example:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature update <id> --status deferred --db porting.db \
|
|
--override "blocked: requires <missing dependency> for non-stub implementation"
|
|
```
|
|
|
|
---
|
|
|
|
### Task 1: Batch Setup and Baseline
|
|
|
|
**Files:**
|
|
- Modify: `porting.db`
|
|
- Read: `golang/nats-server/server/filestore.go`
|
|
- Read: `docs/plans/2026-02-27-batch-13-filestore-read-query-design.md`
|
|
|
|
**Step 1: Confirm batch readiness**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch show 13 --db porting.db
|
|
```
|
|
|
|
Expected: Batch 13 displayed with dependency on Batch 12.
|
|
|
|
**Step 2: Start batch**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch start 13 --db porting.db
|
|
```
|
|
|
|
Expected: Batch status changes to in-progress (or equivalent accepted state).
|
|
|
|
**Step 3: Claim all 8 features as `stub`**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "1006-1011,1014-1015" --set-status stub --db porting.db --execute
|
|
```
|
|
|
|
Expected: All 8 features updated to `stub`.
|
|
|
|
**Step 4: Run baseline build and unit tests**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet build dotnet/
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
```
|
|
|
|
Expected: Baseline captured before feature changes.
|
|
|
|
**Step 5: Commit baseline checkpoint**
|
|
|
|
```bash
|
|
git add porting.db docs/plans/2026-02-27-batch-13-filestore-read-query-design.md docs/plans/2026-02-27-batch-13-filestore-read-query-plan.md
|
|
git commit -m "plan(batch13): establish filestore read/query baseline and protocol"
|
|
```
|
|
|
|
---
|
|
|
|
### Task 2: Group A Features (1006, 1007, 1008) Skip-First-Block Helpers
|
|
|
|
**Files:**
|
|
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs`
|
|
- Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreReadQueryTests.cs`
|
|
- Optional Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/MessageBlock.cs` (only if helper accessors are required)
|
|
|
|
**Step 1: Read Go source slice for Group A**
|
|
|
|
Read:
|
|
|
|
```bash
|
|
sed -n '3241,3307p' golang/nats-server/server/filestore.go
|
|
```
|
|
|
|
Expected: Exact behavior for `checkSkipFirstBlock`, `checkSkipFirstBlockMulti`, `selectSkipFirstBlock`.
|
|
|
|
**Step 2: Write failing tests for block-selection behavior**
|
|
|
|
Add tests covering:
|
|
|
|
- `filter=""` and `filter=">"` returns `bi + 1`.
|
|
- Literal filter with no `psim` match returns `ErrStoreEOF`.
|
|
- `stop <= currentBlockIndex` returns `ErrStoreEOF`.
|
|
- `start > currentBlockIndex` jumps to selected block index.
|
|
- Multi-filter path uses `SimpleSublist` intersection semantics.
|
|
|
|
**Step 3: Run targeted tests to verify failure**
|
|
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
|
|
--filter "FullyQualifiedName~JetStreamFileStoreReadQueryTests.CheckSkipFirstBlock|FullyQualifiedName~JetStreamFileStoreReadQueryTests.SelectSkipFirstBlock"
|
|
```
|
|
|
|
Expected: Failing tests indicating missing or incorrect behavior.
|
|
|
|
**Step 4: Implement Group A methods in `FileStore.cs`**
|
|
|
|
Implement logic equivalent to Go:
|
|
|
|
```csharp
|
|
private (int Next, Exception? Error) SelectSkipFirstBlock(int bi, uint start, uint stop)
|
|
{
|
|
var mbi = _blks[bi].Index;
|
|
if (stop <= mbi)
|
|
return (-1, StoreErrors.ErrStoreEOF);
|
|
if (start > mbi && _bim.TryGetValue(start, out var mb) && mb != null)
|
|
{
|
|
var (ni, _) = SelectMsgBlockWithIndex(mb.Last.Seq);
|
|
return (ni, null);
|
|
}
|
|
return (bi + 1, null);
|
|
}
|
|
```
|
|
|
|
Use the same boundary rules for `CheckSkipFirstBlock` and multi-filter variant.
|
|
|
|
**Step 5: Run targeted tests to green**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
|
|
--filter "FullyQualifiedName~JetStreamFileStoreReadQueryTests.CheckSkipFirstBlock|FullyQualifiedName~JetStreamFileStoreReadQueryTests.SelectSkipFirstBlock"
|
|
```
|
|
|
|
Expected: Pass.
|
|
|
|
**Step 6: Run Stub Detection Check, Build Gate, Test Gate**
|
|
|
|
Run all commands from `MANDATORY VERIFICATION PROTOCOL`.
|
|
|
|
**Step 7: Update statuses for Group A**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "1006-1008" --set-status complete --db porting.db --execute
|
|
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "1006-1008" --set-status verified --db porting.db --execute
|
|
```
|
|
|
|
Expected: IDs `1006-1008` set to verified with recorded evidence.
|
|
|
|
**Step 8: Run Checkpoint Protocol and commit**
|
|
|
|
```bash
|
|
git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs \
|
|
dotnet/src/ZB.MOM.NatsNet.Server/JetStream/MessageBlock.cs \
|
|
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreReadQueryTests.cs \
|
|
porting.db
|
|
git commit -m "feat(batch13): port filestore skip-first-block query helpers"
|
|
```
|
|
|
|
---
|
|
|
|
### Task 3: Group B Features (1009, 1010, 1011) Filtered Pending Helpers
|
|
|
|
**Files:**
|
|
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreReadQueryTests.cs`
|
|
|
|
**Step 1: Read Go source slice for Group B**
|
|
|
|
```bash
|
|
sed -n '3308,3503p' golang/nats-server/server/filestore.go
|
|
```
|
|
|
|
Expected: Behavior for `numFilteredPending*`, stale `fblk` correction, optional last-seq logic.
|
|
|
|
**Step 2: Write failing tests for filtered pending**
|
|
|
|
Add tests for:
|
|
|
|
- All-subject short-circuit (`filter=""` and `filter=">"`).
|
|
- No-match returns zeroed `SimpleState`.
|
|
- Literal and wildcard totals from `psim`.
|
|
- `NumFilteredPendingNoLast` leaves `Last == 0`.
|
|
- Stale `Psi.Fblk` is corrected after first miss path.
|
|
|
|
**Step 3: Run targeted tests to verify failure**
|
|
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
|
|
--filter "FullyQualifiedName~JetStreamFileStoreReadQueryTests.NumFilteredPending"
|
|
```
|
|
|
|
Expected: Fail until implementation is in place.
|
|
|
|
**Step 4: Implement Group B methods**
|
|
|
|
Port Go behavior:
|
|
|
|
- `NumFilteredPending` delegates to with-last variant (`includeLast=true`).
|
|
- `NumFilteredPendingNoLast` delegates with `includeLast=false`.
|
|
- `NumFilteredPendingWithLast`:
|
|
- Calculates totals from `_psim`.
|
|
- Resolves first via start block then forward scan.
|
|
- Schedules `Psi.Fblk` correction under write lock if stale.
|
|
- Computes last only when requested.
|
|
|
|
**Step 5: Run targeted + related tests**
|
|
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
|
|
--filter "FullyQualifiedName~JetStreamFileStoreReadQueryTests.NumFilteredPending|FullyQualifiedName~JetStreamFileStoreTests"
|
|
```
|
|
|
|
Expected: Pass.
|
|
|
|
**Step 6: Run Stub Detection Check, Build Gate, Test Gate**
|
|
|
|
Run all commands from `MANDATORY VERIFICATION PROTOCOL`.
|
|
|
|
**Step 7: Update statuses for Group B**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "1009-1011" --set-status complete --db porting.db --execute
|
|
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "1009-1011" --set-status verified --db porting.db --execute
|
|
```
|
|
|
|
**Step 8: Run Checkpoint Protocol and commit**
|
|
|
|
```bash
|
|
git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs \
|
|
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreReadQueryTests.cs \
|
|
porting.db
|
|
git commit -m "feat(batch13): port filestore filtered-pending query helpers"
|
|
```
|
|
|
|
---
|
|
|
|
### Task 4: Group C Features (1014, 1015) Last-Sequence and Filter-All Helpers
|
|
|
|
**Files:**
|
|
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreReadQueryTests.cs`
|
|
|
|
**Step 1: Read Go source slice for Group C**
|
|
|
|
```bash
|
|
sed -n '3504,3571p' golang/nats-server/server/filestore.go
|
|
```
|
|
|
|
Expected: `allLastSeqsLocked` and `filterIsAll` behavior details.
|
|
|
|
**Step 2: Write failing tests for Group C**
|
|
|
|
Add tests for:
|
|
|
|
- `AllLastSeqsLocked` returns sorted last sequence list.
|
|
- No messages or no subject tracking returns empty/nil equivalent.
|
|
- Lazy `lastNeedsUpdate` path recalculates before collecting sequence.
|
|
- `FilterIsAll` true for reordered equivalent subject set.
|
|
- `FilterIsAll` false for count mismatch or non-subset match.
|
|
|
|
**Step 3: Run targeted tests to verify failure**
|
|
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
|
|
--filter "FullyQualifiedName~JetStreamFileStoreReadQueryTests.AllLastSeqsLocked|FullyQualifiedName~JetStreamFileStoreReadQueryTests.FilterIsAll"
|
|
```
|
|
|
|
Expected: Fail until implementation is complete.
|
|
|
|
**Step 4: Implement Group C methods**
|
|
|
|
Port behavior:
|
|
|
|
- Reverse block walk collecting per-subject last sequence once.
|
|
- Keep `subs` set to avoid duplicates.
|
|
- Sort final sequence array before return.
|
|
- `FilterIsAll` compares sorted `filters` to sorted configured subjects using subset-match check.
|
|
|
|
**Step 5: Run targeted + regression tests**
|
|
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
|
|
--filter "FullyQualifiedName~JetStreamFileStoreReadQueryTests.AllLastSeqsLocked|FullyQualifiedName~JetStreamFileStoreReadQueryTests.FilterIsAll|FullyQualifiedName~StorageEngineTests.FileStoreMultiLastSeqsAndLoadLastMsgWithLazySubjectState_ShouldSucceed|FullyQualifiedName~JetStreamMemoryStoreTests.MemStoreAllLastSeqs_ShouldSucceed|FullyQualifiedName~JetStreamMemoryStoreTests.MemStoreMultiLastSeqs_ShouldSucceed"
|
|
```
|
|
|
|
Expected: Pass.
|
|
|
|
**Step 6: Run Stub Detection Check, Build Gate, Test Gate**
|
|
|
|
Run all commands from `MANDATORY VERIFICATION PROTOCOL`.
|
|
|
|
**Step 7: Update statuses for Group C**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "1014-1015" --set-status complete --db porting.db --execute
|
|
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "1014-1015" --set-status verified --db porting.db --execute
|
|
```
|
|
|
|
**Step 8: Run Checkpoint Protocol and commit**
|
|
|
|
```bash
|
|
git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs \
|
|
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamFileStoreReadQueryTests.cs \
|
|
porting.db
|
|
git commit -m "feat(batch13): port filestore all-last-seqs and filter-is-all helpers"
|
|
```
|
|
|
|
---
|
|
|
|
### Task 5: Batch Completion and Handoff
|
|
|
|
**Files:**
|
|
- Modify: `porting.db`
|
|
- Optional Modify: `reports/current.md` (if report script updates it)
|
|
|
|
**Step 1: Full verification sweep**
|
|
|
|
```bash
|
|
dotnet build dotnet/
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.IntegrationTests/
|
|
```
|
|
|
|
Expected: Green build and tests (or clearly documented pre-existing failures).
|
|
|
|
**Step 2: Audit features**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- audit --type features --db porting.db
|
|
```
|
|
|
|
Expected: Batch 13 IDs classified consistently with implementation.
|
|
|
|
**Step 3: Complete batch**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch complete 13 --db porting.db
|
|
```
|
|
|
|
Expected: Batch 13 completes if all required statuses are valid.
|
|
|
|
**Step 4: Refresh report and inspect newly unblocked work**
|
|
|
|
```bash
|
|
./reports/generate-report.sh
|
|
dotnet run --project tools/NatsNet.PortTracker -- dependency ready --db porting.db
|
|
```
|
|
|
|
Expected: Updated report and visibility into next available batches.
|
|
|
|
---
|
|
|
|
## Evidence Log Template (Use During Execution)
|
|
|
|
For each feature ID, capture:
|
|
|
|
- Go reference: file + line range reviewed.
|
|
- Test cases added/updated.
|
|
- Targeted test command + pass summary.
|
|
- Build command + pass summary.
|
|
- Stub scan output status.
|
|
- PortTracker status command(s) executed.
|
|
|
|
This evidence is required before any `verified` transition.
|