Generated design docs and implementation plans via Codex for: - Batch 37: Stream Messages - Batch 38: Consumer Lifecycle - Batch 39: Consumer Dispatch - Batch 40: MQTT Server/JSA - Batch 41: MQTT Client/IO All plans include mandatory verification protocol and anti-stub guardrails. Updated batches.md with file paths and planned status. All 42 batches (0-41) now have design docs and implementation plans.
419 lines
15 KiB
Markdown
419 lines
15 KiB
Markdown
# Batch 39 Consumer Dispatch Implementation Plan
|
|
|
|
> **For Codex:** REQUIRED SUB-SKILL: Use `executeplan` to implement this plan task-by-task.
|
|
|
|
**Goal:** Port and verify Batch 39 (`Consumer Dispatch`) from `server/consumer.go` so all 93 mapped features and 53 mapped tests are either genuinely implemented/verified or explicitly deferred with concrete blocker reasons.
|
|
|
|
**Architecture:** Implement Batch 39 in five feature groups (`18/18/19/19/19`) with dispatch-focused `NatsConsumer` partial decomposition. After each feature group, execute mapped test waves and enforce strict evidence gates (stub scan, build gate, targeted tests, checkpoint) before any 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-39-consumer-dispatch-design.md`
|
|
|
|
---
|
|
|
|
## Batch 39 Scope
|
|
|
|
- Batch ID: `39`
|
|
- Name: `Consumer Dispatch`
|
|
- Dependency: `38`
|
|
- Go source: `golang/nats-server/server/consumer.go`
|
|
- Features: `93`
|
|
- Tests: `53`
|
|
|
|
If `dotnet` is not on `PATH`, use:
|
|
|
|
```bash
|
|
DOTNET=/usr/local/share/dotnet/dotnet
|
|
```
|
|
|
|
Primary production files (expected):
|
|
|
|
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Waiting.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Pull.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Acks.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Delivery.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Redelivery.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.ReplyParsing.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Shutdown.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Consumers.cs`
|
|
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/StreamTypes.cs`
|
|
|
|
Primary test files (expected):
|
|
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/NatsConsumerTests.cs`
|
|
- Modify/Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/NatsConsumerDispatchTests.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsConsumerTests.Impltests.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.Impltests.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests1.Impltests.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JwtProcessorTests.Impltests.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs`
|
|
- Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests1.Impltests.cs`
|
|
|
|
---
|
|
|
|
## MANDATORY VERIFICATION PROTOCOL
|
|
|
|
> **NON-NEGOTIABLE:** Every Batch 39 feature and test must pass this protocol. No shortcuts.
|
|
|
|
### 1. Dependency Preflight and Baseline
|
|
|
|
Run before touching statuses:
|
|
|
|
```bash
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 38 --db porting.db
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 39 --db porting.db
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- batch ready --db porting.db
|
|
```
|
|
|
|
Start Batch 39 only when ready:
|
|
|
|
```bash
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- batch start 39 --db porting.db
|
|
```
|
|
|
|
Capture baseline:
|
|
|
|
```bash
|
|
$DOTNET build dotnet/
|
|
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
```
|
|
|
|
### 2. What Counts as a Real Port
|
|
|
|
A **feature** is real only if all are true:
|
|
|
|
1. Mapped method/type exists and contains behavioral logic (not placeholder control flow).
|
|
2. Code path is exercised by at least one behavioral test.
|
|
3. Stub scan, build gate, and targeted tests are green.
|
|
4. Status promotion has traceable evidence.
|
|
|
|
A **test** is real only if all are true:
|
|
|
|
1. Has Arrange/Act/Assert.
|
|
2. Calls production code from `ZB.MOM.NatsNet.Server.*`.
|
|
3. Uses meaningful Shouldly assertions on Act results/effects.
|
|
4. Contains no stub/template patterns.
|
|
|
|
### 3. Per-Feature Verification Loop (REQUIRED per feature ID)
|
|
|
|
1. Inspect mapped feature and Go source intent:
|
|
```bash
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- feature show <feature_id> --db porting.db
|
|
```
|
|
2. Claim the feature:
|
|
```bash
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- feature update <feature_id> --status stub --db porting.db
|
|
```
|
|
3. Add/adjust at least one behavioral test for the feature.
|
|
4. Implement minimal correct logic.
|
|
5. Run **Stub Detection Check**.
|
|
6. Run **Build Gate**.
|
|
7. Run relevant **Test Gate** filters.
|
|
8. Promote proven feature to `complete` (or `verified` only after checkpoint evidence).
|
|
|
|
### 4. Per-Test Verification Loop (REQUIRED per test ID)
|
|
|
|
1. Inspect mapped test and Go source:
|
|
```bash
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- test show <test_id> --db porting.db
|
|
```
|
|
2. Claim the test:
|
|
```bash
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- test update <test_id> --status stub --db porting.db
|
|
```
|
|
3. Port complete behavior.
|
|
4. Run single test and verify discovery:
|
|
```bash
|
|
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ \
|
|
--filter "FullyQualifiedName~<ClassName>.<MethodName>" --verbosity normal
|
|
```
|
|
5. Confirm `Passed: 1, Failed: 0` (never `Passed: 0`).
|
|
6. Run class-level filter.
|
|
7. Run **Stub Detection Check** + **Build Gate**.
|
|
8. Promote proven test to `complete` (or `verified` only after checkpoint evidence).
|
|
|
|
### 5. Stub Detection Check (REQUIRED after each feature/test loop)
|
|
|
|
```bash
|
|
changed_files=$(git diff --name-only -- dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests | rg "\\.cs$" || true)
|
|
if [ -n "$changed_files" ]; then
|
|
echo "$changed_files" | xargs rg -n "(NotImplementedException|// TODO|// PLACEHOLDER|Assert\\.True\\(true\\)|Assert\\.Pass\\(\\)|var goFile = \"server/|\\.ShouldContain\\(\"Should\"\\)|GetRequiredApiLevel\\(new Dictionary<string, string>\\)\\.ShouldBe\\(string\\.Empty\\)|=>\\s*default;|return\\s+default;|return\\s+null;\\s*$|throw new Exception\\(\"TODO\"\\))"
|
|
fi
|
|
```
|
|
|
|
Any match blocks status promotion until fixed or explicitly deferred.
|
|
|
|
### 6. Build Gate (REQUIRED)
|
|
|
|
```bash
|
|
$DOTNET build dotnet/
|
|
```
|
|
|
|
Run after every feature loop, every test loop, before any `batch-update`, and at each task checkpoint.
|
|
|
|
### 7. Test Gate (REQUIRED)
|
|
|
|
Run the smallest relevant set after each change; run all of the following at checkpoints:
|
|
|
|
```bash
|
|
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~JetStream.NatsConsumerTests|FullyQualifiedName~JetStream.NatsConsumerDispatchTests"
|
|
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ImplBacklog.NatsConsumerTests|FullyQualifiedName~ImplBacklog.JetStreamEngineTests"
|
|
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ --filter "FullyQualifiedName~ImplBacklog.JetStreamClusterTests1|FullyQualifiedName~ImplBacklog.ConcurrencyTests1|FullyQualifiedName~ImplBacklog.JwtProcessorTests|FullyQualifiedName~ImplBacklog.RouteHandlerTests"
|
|
```
|
|
|
|
Checkpoint/full gate:
|
|
|
|
```bash
|
|
$DOTNET test dotnet/tests/ZB.MOM.NatsNet.Server.Tests/
|
|
```
|
|
|
|
### 8. Status Update Protocol (HARD LIMIT: 15 IDs per batch-update)
|
|
|
|
- Never send more than `15` IDs per `feature batch-update` or `test batch-update` call.
|
|
- Never mark `verified` without checkpoint evidence.
|
|
- Never update IDs outside the active task scope.
|
|
- Keep blocked items `deferred` with specific reason text.
|
|
|
|
Use:
|
|
|
|
```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
|
|
```
|
|
|
|
### 9. Checkpoint Protocol Between Tasks (REQUIRED)
|
|
|
|
Before moving to the next task:
|
|
|
|
1. Run **Stub Detection Check**.
|
|
2. Run **Build Gate**.
|
|
3. Run **Test Gate** (targeted filters + full unit test suite).
|
|
4. Apply status updates in max-15-ID chunks only.
|
|
5. Commit the task checkpoint before continuing.
|
|
|
|
---
|
|
|
|
## ANTI-STUB GUARDRAILS (NON-NEGOTIABLE)
|
|
|
|
### Forbidden Patterns
|
|
|
|
The following are forbidden in Batch 39 feature/test work:
|
|
|
|
- `throw new NotImplementedException()`
|
|
- Empty mapped method bodies / no-op ports
|
|
- `TODO` / `PLACEHOLDER` comments as unresolved implementation markers
|
|
- `Assert.True(true)` / `Assert.Pass()`
|
|
- Template assertions disconnected from behavior:
|
|
- `var goFile = "server/..."`
|
|
- `"<name>".ShouldContain("Should")`
|
|
- `GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty)` as primary assertion
|
|
- Placeholder return shortcuts in mapped code:
|
|
- `=> default;`
|
|
- `return default;`
|
|
- `return null;`
|
|
- Catch-and-ignore blocks used only to force green tests
|
|
|
|
### Hard Limits
|
|
|
|
- Max feature group size: `~20`.
|
|
- Max IDs per `feature batch-update`: `15`.
|
|
- Max IDs per `test batch-update`: `15`.
|
|
- One active feature loop at a time.
|
|
- One active test loop at a time.
|
|
- Mandatory checkpoint between tasks.
|
|
- No `verified` promotion without checkpoint evidence.
|
|
|
|
### If You Get Stuck (REQUIRED)
|
|
|
|
1. Stop on the current feature/test immediately.
|
|
2. Do **not** stub or fake-pass.
|
|
3. Mark item `deferred` with a specific blocker reason.
|
|
4. Continue with the next unblocked item.
|
|
|
|
Feature deferral:
|
|
|
|
```bash
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- \
|
|
feature update <feature_id> --status deferred --override "blocked: <specific reason>" --db porting.db
|
|
```
|
|
|
|
Test deferral:
|
|
|
|
```bash
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- \
|
|
test update <test_id> --status deferred --override "blocked: <specific reason>" --db porting.db
|
|
```
|
|
|
|
`deferred` with concrete reason is the correct fallback; stubs are not.
|
|
|
|
---
|
|
|
|
## Feature Groups (max ~20 each)
|
|
|
|
### Group A (18): waiting queue and pull ingress
|
|
|
|
IDs:
|
|
`696,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715`
|
|
|
|
### Group B (18): dispatch core, ack floor, inbound loops
|
|
|
|
IDs:
|
|
`716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733`
|
|
|
|
### Group C (19): delivery, flow-control, redelivery basics
|
|
|
|
IDs:
|
|
`734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752`
|
|
|
|
### Group D (19): reply parsing, seq selection, identity helpers
|
|
|
|
IDs:
|
|
`753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,772`
|
|
|
|
### Group E (19): purge/stop/no-interest/monitor signaling
|
|
|
|
IDs:
|
|
`774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792`
|
|
|
|
## Test Waves
|
|
|
|
### Wave T1 (14): `NatsConsumerTests`
|
|
|
|
IDs:
|
|
`1230,1232,1251,1261,1265,1267,1273,1277,1283,1284,1285,1286,1339,1370`
|
|
|
|
### Wave T2 (17): `JetStreamEngineTests` (pull/ack-first half)
|
|
|
|
IDs:
|
|
`1469,1484,1485,1486,1487,1488,1489,1490,1492,1493,1495,1496,1498,1499,1500,1501,1502`
|
|
|
|
### Wave T3 (17): `JetStreamEngineTests` (pending/purge-second half)
|
|
|
|
IDs:
|
|
`1508,1514,1515,1516,1517,1518,1519,1520,1521,1522,1526,1530,1531,1545,1547,1567,1665`
|
|
|
|
### Wave T4 (5): cross-suite integration/backlog edges
|
|
|
|
IDs:
|
|
`814,1840,2389,2407,2858`
|
|
|
|
---
|
|
|
|
### Task 1: Preflight and Baseline
|
|
|
|
**Files:**
|
|
- Read: `docs/plans/2026-02-27-batch-39-consumer-dispatch-design.md`
|
|
- Read: `golang/nats-server/server/consumer.go`
|
|
|
|
**Steps:**
|
|
1. Run dependency preflight and confirm Batch 39 readiness.
|
|
2. Start Batch 39.
|
|
3. Capture baseline build + full unit test results.
|
|
4. Record baseline pass/fail/skip counts.
|
|
|
|
### Task 2: Implement Feature Group A + Test Wave T1
|
|
|
|
**Files:**
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Waiting.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Pull.cs`
|
|
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/StreamTypes.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/NatsConsumerTests.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsConsumerTests.Impltests.cs`
|
|
|
|
**Steps:**
|
|
1. Process each feature ID in Group A through the per-feature loop.
|
|
2. Port all tests in Wave T1 with per-test loop.
|
|
3. Run checkpoint protocol.
|
|
4. Update Group A/T1 statuses in max-15-ID chunks.
|
|
5. Commit.
|
|
|
|
### Task 3: Implement Feature Group B
|
|
|
|
**Files:**
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Pull.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Acks.cs`
|
|
- Modify/Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/JetStream/NatsConsumerDispatchTests.cs`
|
|
|
|
**Steps:**
|
|
1. Process Group B feature IDs through per-feature loop.
|
|
2. Add deterministic unit tests for dispatch loop and ack-floor transitions.
|
|
3. Run checkpoint protocol.
|
|
4. Update Group B feature statuses in max-15-ID chunks.
|
|
5. Commit.
|
|
|
|
### Task 4: Implement Feature Group C + Test Wave T2
|
|
|
|
**Files:**
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Delivery.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Redelivery.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.Impltests.cs`
|
|
|
|
**Steps:**
|
|
1. Process Group C feature IDs through per-feature loop.
|
|
2. Port Wave T2 tests through per-test loop.
|
|
3. Run checkpoint protocol.
|
|
4. Update Group C/T2 statuses in max-15-ID chunks.
|
|
5. Commit.
|
|
|
|
### Task 5: Implement Feature Group D + Test Wave T3
|
|
|
|
**Files:**
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.ReplyParsing.cs`
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsStream.Consumers.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.Impltests.cs`
|
|
|
|
**Steps:**
|
|
1. Process Group D feature IDs through per-feature loop.
|
|
2. Port Wave T3 tests through per-test loop.
|
|
3. Run checkpoint protocol.
|
|
4. Update Group D/T3 statuses in max-15-ID chunks.
|
|
5. Commit.
|
|
|
|
### Task 6: Implement Feature Group E + Test Wave T4
|
|
|
|
**Files:**
|
|
- Modify/Create: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.Dispatch.Shutdown.cs`
|
|
- Modify: `dotnet/src/ZB.MOM.NatsNet.Server/JetStream/NatsConsumer.cs`
|
|
- Modify/Create: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests1.Impltests.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests1.Impltests.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JwtProcessorTests.Impltests.cs`
|
|
- Modify: `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs`
|
|
|
|
**Steps:**
|
|
1. Process Group E feature IDs through per-feature loop.
|
|
2. Port Wave T4 tests through per-test loop.
|
|
3. Run checkpoint protocol.
|
|
4. Update Group E/T4 statuses in max-15-ID chunks.
|
|
5. Commit.
|
|
|
|
### Task 7: Final Batch 39 Verification and Closure
|
|
|
|
**Files:**
|
|
- Modify: `porting.db`
|
|
- Generate: `reports/current.md`
|
|
|
|
**Steps:**
|
|
1. Run full stub scan over changed source + test files.
|
|
2. Run full build gate.
|
|
3. Run full unit test suite; require `Failed: 0`.
|
|
4. Run:
|
|
```bash
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- batch show 39 --db porting.db
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- report summary --db porting.db
|
|
```
|
|
5. If all IDs are complete/verified/deferred-with-reason, execute batch completion:
|
|
```bash
|
|
$DOTNET run --project tools/NatsNet.PortTracker -- batch complete 39 --db porting.db
|
|
```
|
|
6. Generate updated report and commit:
|
|
```bash
|
|
./reports/generate-report.sh
|
|
git add dotnet/src/ZB.MOM.NatsNet.Server dotnet/tests/ZB.MOM.NatsNet.Server.Tests porting.db reports/
|
|
git commit -m "feat(batch39): implement consumer dispatch features and tests"
|
|
```
|