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.
7.3 KiB
Batch 24 Leaf Nodes Design
Date: 2026-02-27
Batch: 24 (Leaf Nodes)
Scope: Design only. No implementation in this document.
Problem
Batch 24 ports leaf-node connection handling from golang/nats-server/server/leafnode.go into the .NET server.
- Features:
67(all currentlydeferred) - Tests:
2(both currentlydeferred) - Dependencies: batches
19and23 - Go source:
server/leafnode.go - Batch status:
pending
Leaf-node behavior touches client protocol parsing, solicited/accepted leaf lifecycle, account interest propagation, and cross-cluster subscription semantics.
Context Findings
Collected with:
dotnet run --project tools/NatsNet.PortTracker -- batch show 24 --db porting.dbdotnet run --project tools/NatsNet.PortTracker -- batch list --db porting.dbdotnet run --project tools/NatsNet.PortTracker -- report summary --db porting.db
Additional repository findings:
- .NET already has leaf data models in
dotnet/src/ZB.MOM.NatsNet.Server/LeafNode/LeafNodeTypes.cs(Leaf,LeafNodeCfg,LeafConnectInfo) but the Batch 24 behavior surface is largely unimplemented. ClientConnectioncurrently has explicit leaf placeholders (IsHubLeafNode,RemoteCluster) and parser-level leaf argument helpers still marked as stubs/delegates.LeafNodeHandlerTests.Impltests.csandRouteHandlerTests.Impltests.csstill contain placeholder-style tests and do not currently include the two Batch 24 mapped methods.- Batch 24 mapped tests are:
1966(LeafNodeHandlerTests.LeafNodeRoutedSubKeyDifferentBetweenLeafSubAndRoutedSub_ShouldSucceed)2825(RouteHandlerTests.ClusterQueueGroupWeightTrackingLeak_ShouldSucceed)
Constraints and Success Criteria
Constraints:
- Follow project standards in
docs/standards/dotnet-standards.md. - Keep behavior equivalent to Go intent, but idiomatic C# (.NET 10, nullable enabled).
- No placeholder implementations, no fake-pass tests, no status promotion without evidence.
- Feature work must be grouped into chunks of <= ~20 features.
- Batch 24 execution must wait for dependency readiness (batches 19 and 23).
Success criteria:
- All 67 features are either implemented and verified, or explicitly deferred with a concrete blocker reason.
- Both mapped tests are implemented as real behavioral tests and pass.
- Leaf-related parser/account regression tests pass before
complete -> verified. - Batch 24 can be completed through PortTracker without overrides for unverifiable work.
Approaches
Approach A: Single monolithic leaf file
Implement all 67 methods in one large NatsServer.LeafNodes.cs and keep most ClientConnection work in ClientConnection.cs.
Trade-offs:
- Pros: fewer files to navigate.
- Cons: very high review risk, difficult evidence tracking, poor checkpoint isolation.
Approach B (Recommended): Domain-segmented partials by leaf lifecycle stage
Split implementation by responsibility:
- Leaf validation/config/bootstrap
- Connect/handshake/lifecycle
- Interest propagation/account/subscription maps
- Message/sub/unsub processing and websocket solicit path
Trade-offs:
- Pros: aligns to
leafnode.gosections, cleaner verification gates, easier status chunking and rollback. - Cons: more file coordination.
Approach C: Test-first only on mapped tests, then fill remaining features
Start with the two mapped tests and then backfill features.
Trade-offs:
- Pros: immediate test signal.
- Cons: two tests under-cover 67 features, making false confidence likely unless strict feature-level verification is enforced.
Recommended Design
Use Approach B with four feature groups (18/18/14/17 IDs) mapped to Go line ranges and .NET class ownership.
Architecture
ClientConnectionpartials handle leaf protocol parsing, leaf connect payload processing, sub/unsub deltas, permission violations, and websocket solicitation.NatsServerpartials handle remote solicitation, outbound reconnect/connect loops, listener accept loop, leaf info dissemination, and connection registration lifecycle.LeafNodehelper surface (LeafNodeHandler+LeafNodeCfgmethods) centralizes validation and key generation utilities used by both server and client paths.Accountupdates coverUpdateLeafNodesExsemantics and gateway/leaf interest propagation coupling.
Proposed File Map
Primary production files:
- Create:
dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.LeafNodes.cs - Create:
dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.LeafNodes.ConfigAndConnect.cs - Create:
dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.LeafNodes.Subscriptions.cs - Create:
dotnet/src/ZB.MOM.NatsNet.Server/LeafNode/LeafNodeHandler.cs - Modify:
dotnet/src/ZB.MOM.NatsNet.Server/LeafNode/LeafNodeTypes.cs(forLeafNodeCfgmethod surface) - Modify:
dotnet/src/ZB.MOM.NatsNet.Server/Accounts/Account.cs - Modify:
dotnet/src/ZB.MOM.NatsNet.Server/Protocol/ProtocolParser.cs - Modify (as needed):
dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Lifecycle.cs
Mapped test files:
- Modify:
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/LeafNodeHandlerTests.Impltests.cs - Modify:
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RouteHandlerTests.Impltests.cs
Related regression tests:
dotnet/tests/ZB.MOM.NatsNet.Server.Tests/Protocol/ProtocolParserTests.csdotnet/tests/ZB.MOM.NatsNet.Server.Tests/Accounts/ResolverDefaultsOpsTests.csdotnet/tests/ZB.MOM.NatsNet.Server.Tests/ClientTests.cs
Data and Control Flow
- Outbound flow: configured remote leaf nodes -> validate -> pick URL -> connect/proxy/ws path -> leaf CONNECT/INFO handshake -> register connection -> initialize subscription map.
- Inbound flow: accept loop -> create leaf client -> process INFO/CONNECT -> negotiate compression/perms -> account registration and interest sync.
- Interest propagation: account sub changes -> leaf smap deltas -> leaf SUB/UNSUB protocol emission -> inbound leaf message/sub updates -> permission enforcement.
Error Handling Strategy
- Preserve Go failure modes for malformed protocol args, invalid remote config, and loop/duplicate detection paths.
- Prefer explicit guard clauses with clear exceptions over silent default returns.
- On infrastructure blockers, defer with reason rather than introducing placeholders.
Verification Strategy
- Enforce per-feature verification loop (Go read, C# implementation, build, related test run).
- Enforce group-level stub scans and build gate before any
stub -> complete. - Enforce full leaf-related test gate before any
complete -> verified. - Enforce checkpoint protocol (full build + full tests + commit) between every task.
Risks and Mitigations
- Risk: race-prone account/smap updates regress existing account behavior.
- Mitigation: isolate account update logic and require
ResolverDefaultsOpsTestsin every verification wave.
- Mitigation: isolate account update logic and require
- Risk: parser and runtime leaf arg handling diverge.
- Mitigation: keep parser and client leaf arg updates in the same feature group and verify via
ProtocolParserTests.
- Mitigation: keep parser and client leaf arg updates in the same feature group and verify via
- Risk: backlog tests remain placeholders and create false green.
- Mitigation: mandatory anti-stub scans and method-level filters for mapped tests.
Design Approval Basis
This design is based on Batch 24 metadata from PortTracker, existing Batch 0 verification standards, and explicit requirements for feature+test anti-stub guardrails and grouped execution.