Generated design docs and implementation plans via Codex for: - Batch 23: Routes - Batch 24: Leaf Nodes - Batch 25: Gateways - Batch 26: WebSocket - Batch 27: JetStream Core - Batch 28: JetStream API - Batch 29: JetStream Batching - Batch 30: Raft Part 1 All plans include mandatory verification protocol and anti-stub guardrails. Updated batches.md with file paths and planned status.
480 lines
16 KiB
Markdown
480 lines
16 KiB
Markdown
# Batch 29 JetStream Batching Implementation Plan
|
|
|
|
> **For Codex:** REQUIRED SUB-SKILL: Use `executeplan` to implement this plan task-by-task.
|
|
|
|
**Goal:** Port and verify Batch 29 JetStream batching behavior (12 features, 3 tests) from `server/jetstream_batching.go` and mapped `raft_test.go` cases without introducing stubs or unverifiable tracker updates.
|
|
|
|
**Architecture:** Execute in two feature groups and one test group. Group A ports lifecycle/store primitives (`1508-1514`), Group B ports staged/apply/header checks (`1515-1519`, including the large `checkMsgHeadersPreClusteredProposal` surface), then mapped Raft tests are ported/verified. Every ID follows strict per-item evidence gates before status promotion.
|
|
|
|
**Tech Stack:** .NET 10, C# latest, xUnit 3, Shouldly, NSubstitute, PortTracker CLI, SQLite (`porting.db`)
|
|
|
|
**Design doc:** `docs/plans/2026-02-27-batch-29-jetstream-batching-design.md`
|
|
|
|
---
|
|
|
|
## Batch 29 Scope
|
|
|
|
- Batch ID: `29`
|
|
- Name: `JetStream Batching`
|
|
- Dependency: `27`
|
|
- Go source: `golang/nats-server/server/jetstream_batching.go`
|
|
- Features: `1508-1519` (12 total)
|
|
- Tests: `2654,2674,2718`
|
|
|
|
Primary implementation files:
|
|
|
|
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamBatching.cs`
|
|
- Optional split (recommended for readability of feature `1519`):
|
|
- Create/Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamBatching.HeaderChecks.cs`
|
|
- Optional supporting updates only if required by compile/runtime behavior:
|
|
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.cs`
|
|
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamTypes.cs`
|
|
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs`
|
|
|
|
Primary test files:
|
|
|
|
- Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/RaftNodeTests.cs`
|
|
- Modify or Create focused batching tests as needed:
|
|
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamBatchingCoreTests.cs`
|
|
- Existing deferred batching integration placeholders (do not convert to fake unit tests):
|
|
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamBatchingTests.cs`
|
|
|
|
---
|
|
|
|
## MANDATORY VERIFICATION PROTOCOL
|
|
|
|
> **NON-NEGOTIABLE:** Applies to every feature ID and test ID in Batch 29.
|
|
|
|
### Preflight Dependency Gate (REQUIRED before Task 1 coding)
|
|
|
|
1. Verify dependency and readiness:
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch show 27 --db porting.db
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch show 29 --db porting.db
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch ready --db porting.db
|
|
```
|
|
2. Start the batch only when dependency checks pass:
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch start 29 --db porting.db
|
|
```
|
|
3. Baseline gates:
|
|
```bash
|
|
dotnet build dotnet/
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
```
|
|
|
|
### Per-Feature Verification Loop (REQUIRED for each feature ID)
|
|
|
|
For each feature in current task group:
|
|
|
|
1. Inspect mapping and Go span:
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature show <feature_id> --db porting.db
|
|
sed -n '<go_start>,<go_end>p' golang/nats-server/server/jetstream_batching.go
|
|
```
|
|
2. Mark that feature as `stub` before editing:
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature update <feature_id> --status stub --db porting.db
|
|
```
|
|
3. Implement mapped behavior in .NET (no placeholders).
|
|
4. Run **Build Gate**.
|
|
5. Run **Test Gate** (focused tests for changed behavior).
|
|
6. Run **Stub Detection Check** on touched files.
|
|
7. If gates are green and no stubs are detected, promote feature to `complete`:
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature update <feature_id> --status complete --db porting.db
|
|
```
|
|
8. Promote feature IDs to `verified` only after task-level checkpoint passes.
|
|
|
|
### Per-Test Verification Loop (REQUIRED for each test ID)
|
|
|
|
1. Inspect mapped test details and Go source:
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- test show <test_id> --db porting.db
|
|
sed -n '<go_start>,<go_end>p' golang/nats-server/server/raft_test.go
|
|
```
|
|
2. Mark test `stub` before editing:
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- test update <test_id> --status stub --db porting.db
|
|
```
|
|
3. Implement real Arrange/Act/Assert test calling production code.
|
|
4. Run single-test command:
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
|
|
--filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.JetStream.RaftNodeTests.<MethodName>" \
|
|
--verbosity normal
|
|
```
|
|
5. Confirm summary includes `Passed: 1, Failed: 0` (not `Passed: 0`).
|
|
6. Run class-level test gate:
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
|
|
--filter "FullyQualifiedName~ZB.MOM.NatsNet.Server.Tests.JetStream.RaftNodeTests"
|
|
```
|
|
7. Run Stub Detection Check.
|
|
8. Promote test to `complete`, then `verified` at checkpoint when evidence is complete.
|
|
|
|
### Stub Detection Check (REQUIRED after every feature/test loop and each task)
|
|
|
|
Run against touched code:
|
|
|
|
```bash
|
|
git diff --name-only -- dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests \
|
|
| rg "\.cs$" \
|
|
| xargs rg -n "(NotImplementedException|// TODO|// PLACEHOLDER|Assert\\.True\\(true\\)|Assert\\.Pass|throw new Exception\\(\"TODO\"\\)|=>\\s*default;|=>\\s*null;)"
|
|
```
|
|
|
|
Any match in touched methods means the item is not eligible for `complete` or `verified`.
|
|
|
|
### Build Gate (REQUIRED)
|
|
|
|
`dotnet build dotnet/` is mandatory:
|
|
|
|
- after each feature implementation loop
|
|
- after each test implementation loop
|
|
- before any `batch-update`
|
|
- at every task checkpoint
|
|
|
|
### Test Gate (REQUIRED)
|
|
|
|
Minimum per-task gates:
|
|
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStreamBatching"
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~RaftNodeTests"
|
|
```
|
|
|
|
Checkpoint and final gates:
|
|
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
```
|
|
|
|
### Status Update Protocol (HARD LIMIT: max 15 IDs per batch-update)
|
|
|
|
- Allowed path: `deferred/not_started -> stub -> complete -> verified`
|
|
- Use `batch-update` with **at most 15 IDs** per call.
|
|
- Never update IDs outside the current task group.
|
|
- Never mark `verified` without corresponding build/test/stub-scan evidence.
|
|
- If audit rejects status change, use `--override "<specific reason>"` only with explicit evidence.
|
|
|
|
Templates:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "<max 15 ids>" --set-status <stub|complete|verified> --db porting.db --execute
|
|
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
test batch-update --ids "<max 15 ids>" --set-status <stub|complete|verified> --db porting.db --execute
|
|
```
|
|
|
|
### Checkpoint Protocol Between Tasks (REQUIRED)
|
|
|
|
At the end of each task before starting the next task:
|
|
|
|
1. Run Stub Detection Check.
|
|
2. Run Build Gate.
|
|
3. Run task-relevant Test Gate.
|
|
4. Run full unit suite:
|
|
```bash
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
```
|
|
5. Update status IDs for current task only (max 15 IDs per command).
|
|
6. Commit checkpoint changes.
|
|
|
|
---
|
|
|
|
## ANTI-STUB GUARDRAILS (NON-NEGOTIABLE)
|
|
|
|
### Forbidden Patterns (Features + Tests)
|
|
|
|
Any of these in touched methods means the work is a stub and must not be promoted:
|
|
|
|
- `throw new NotImplementedException()`
|
|
- Empty mapped method bodies
|
|
- Placeholder comments: `// TODO`, `// PLACEHOLDER`, `// later`
|
|
- Fake-pass assertions: `Assert.True(true)`, `Assert.Pass()`
|
|
- Tests that never call production code in `ZB.MOM.NatsNet.Server`
|
|
- Constant-return placeholders for non-trivial logic (`return null;`, `return 0;`, `return false;`, `return string.Empty;`) without Go-equivalent behavior
|
|
- Catch-all exception swallowing used to force pass behavior
|
|
|
|
### Hard Limits
|
|
|
|
- Max feature IDs per group: `~20`
|
|
- Max IDs per `feature/test batch-update`: `15`
|
|
- One active feature loop at a time
|
|
- No `verified` promotion unless build + targeted tests + stub scan are green
|
|
- One checkpoint commit per task minimum
|
|
- Feature `1519` must not be merged as partial/no-op behavior
|
|
|
|
### If You Get Stuck (MANDATORY)
|
|
|
|
1. Stop work on the blocked ID immediately.
|
|
2. Do **not** leave placeholder code or fake tests.
|
|
3. Mark the blocked item `deferred` with specific reason:
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- feature update <id> --status deferred --override "blocked: <specific reason>" --db porting.db
|
|
dotnet run --project tools/NatsNet.PortTracker -- test update <id> --status deferred --override "blocked: <specific reason>" --db porting.db
|
|
```
|
|
4. Move to the next unblocked ID in the same task.
|
|
5. Deferred-with-reason is correct behavior; stubs are not.
|
|
|
|
---
|
|
|
|
## Feature/Test Grouping (max ~20 per group)
|
|
|
|
### Group A (7 features): Batch lifecycle + store creation
|
|
|
|
`1508,1509,1510,1511,1512,1513,1514`
|
|
|
|
### Group B (5 features): Staged/apply state + pre-proposal header checks
|
|
|
|
`1515,1516,1517,1518,1519`
|
|
|
|
### Group C (3 tests): Raft-node behavioral tests mapped to batch 29
|
|
|
|
`2654,2674,2718`
|
|
|
|
---
|
|
|
|
### Task 1: Preflight and Batch Start
|
|
|
|
**Files:**
|
|
|
|
- Read: `docs/standards/dotnet-standards.md`
|
|
- Read: `docs/plans/2026-02-27-batch-29-jetstream-batching-design.md`
|
|
- Read: `golang/nats-server/server/jetstream_batching.go`
|
|
- Read: `golang/nats-server/server/raft_test.go` (mapped lines)
|
|
|
|
**Step 1: Dependency/readiness checks**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch show 27 --db porting.db
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch show 29 --db porting.db
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch ready --db porting.db
|
|
```
|
|
|
|
Expected:
|
|
|
|
- Batch 29 is startable, dependency 27 satisfied.
|
|
|
|
**Step 2: Start batch**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch start 29 --db porting.db
|
|
```
|
|
|
|
Expected:
|
|
|
|
- Batch transitions to in-progress.
|
|
|
|
**Step 3: Baseline build/test**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet build dotnet/
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
```
|
|
|
|
Expected:
|
|
|
|
- Known baseline captured before edits.
|
|
|
|
**Step 4: Checkpoint protocol and commit**
|
|
|
|
---
|
|
|
|
### Task 2: Implement Group A Features (`1508-1514`)
|
|
|
|
**Files:**
|
|
|
|
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamBatching.cs`
|
|
- Optional modify if needed by compile/runtime wiring:
|
|
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.cs`
|
|
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamTypes.cs`
|
|
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/FileStore.cs`
|
|
- Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamBatchingCoreTests.cs`
|
|
|
|
**Step 1: Mark Group A as `stub` (single chunk, 7 IDs <= 15)**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "1508,1509,1510,1511,1512,1513,1514" --set-status stub --db porting.db --execute
|
|
```
|
|
|
|
**Step 2: Execute Per-Feature Verification Loop for each ID in Group A**
|
|
|
|
Expected:
|
|
|
|
- Lifecycle/store methods are behaviorally implemented and individually gated.
|
|
|
|
**Step 3: Task-level gates + checkpoint protocol**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet build dotnet/
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStreamBatching"
|
|
```
|
|
|
|
**Step 4: Promote eligible Group A IDs to `complete` (blocked IDs stay `deferred`)**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "<eligible subset of 1508-1514>" --set-status complete --db porting.db --execute
|
|
```
|
|
|
|
**Step 5: After checkpoint evidence, promote eligible Group A IDs to `verified`**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "<eligible subset up to 7 ids>" --set-status verified --db porting.db --execute
|
|
```
|
|
|
|
---
|
|
|
|
### Task 3: Implement Group B Features (`1515-1519`)
|
|
|
|
**Files:**
|
|
|
|
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamBatching.cs`
|
|
- Optional create/modify to isolate large method:
|
|
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamBatching.HeaderChecks.cs`
|
|
- Optional supporting updates if required by dependencies:
|
|
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.cs`
|
|
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamTypes.cs`
|
|
- `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/JetStreamErrors.cs`
|
|
- Test: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/JetStreamBatchingCoreTests.cs`
|
|
|
|
**Step 1: Mark Group B as `stub` (single chunk, 5 IDs <= 15)**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "1515,1516,1517,1518,1519" --set-status stub --db porting.db --execute
|
|
```
|
|
|
|
**Step 2: Execute Per-Feature Verification Loop for each ID in Group B**
|
|
|
|
Notes:
|
|
|
|
- Treat `1519` as its own micro-loop: implement incrementally but only promote when full gate passes.
|
|
- Validate error-path parity (duplicate msg ID, expected sequence checks, schedule/rollup validation, discard-new limits).
|
|
|
|
**Step 3: Task-level gates + checkpoint protocol**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet build dotnet/
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStreamBatching"
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~RaftTypesTests"
|
|
```
|
|
|
|
**Step 4: Promote eligible Group B IDs to `complete` (blocked IDs stay `deferred`)**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "<eligible subset of 1515-1519>" --set-status complete --db porting.db --execute
|
|
```
|
|
|
|
**Step 5: After checkpoint evidence, promote eligible Group B IDs to `verified`**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
feature batch-update --ids "<eligible subset up to 5 ids>" --set-status verified --db porting.db --execute
|
|
```
|
|
|
|
---
|
|
|
|
### Task 4: Implement Group C Tests (`2654,2674,2718`)
|
|
|
|
**Files:**
|
|
|
|
- Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/RaftNodeTests.cs`
|
|
- Optional modify if helper setup reuse is needed:
|
|
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/RaftTypesTests.cs`
|
|
- Source references:
|
|
- `golang/nats-server/server/raft_test.go`
|
|
|
|
**Step 1: Mark tests as `stub`**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
test batch-update --ids "2654,2674,2718" --set-status stub --db porting.db --execute
|
|
```
|
|
|
|
**Step 2: Execute Per-Test Verification Loop for each test ID**
|
|
|
|
Expected:
|
|
|
|
- Each mapped test method is real, discovered, and passing individually.
|
|
|
|
**Step 3: Task-level gates + checkpoint protocol**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet build dotnet/
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~RaftNodeTests"
|
|
```
|
|
|
|
**Step 4: Promote eligible tests to `complete`**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
test batch-update --ids "<eligible subset of 2654,2674,2718>" --set-status complete --db porting.db --execute
|
|
```
|
|
|
|
**Step 5: After checkpoint evidence, promote eligible tests to `verified`**
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- \
|
|
test batch-update --ids "<eligible subset up to 3 ids>" --set-status verified --db porting.db --execute
|
|
```
|
|
|
|
---
|
|
|
|
### Task 5: Batch 29 Final Verification and Closeout
|
|
|
|
**Files:**
|
|
|
|
- Modify: `porting.db`
|
|
- Generate: `reports/current.md` (via report script)
|
|
|
|
**Step 1: Final mandatory gates**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet build dotnet/
|
|
dotnet test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch show 29 --db porting.db
|
|
dotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
|
|
```
|
|
|
|
Expected:
|
|
|
|
- All Batch 29 IDs are `verified` or `deferred` with explicit reasons.
|
|
|
|
**Step 2: Complete batch**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
dotnet run --project tools/NatsNet.PortTracker -- batch complete 29 --db porting.db
|
|
```
|
|
|
|
**Step 3: Generate report + commit**
|
|
|
|
```bash
|
|
./reports/generate-report.sh
|
|
git add dotnet/src/ZB.MOM.NatsNet.Server/JetStream \
|
|
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream \
|
|
porting.db reports/
|
|
git commit -m "feat(batch29): port jetstream batching and mapped raft tests"
|
|
```
|