Add batch plans for batches 23-30 (rounds 12-15)
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.
This commit is contained in:
128
docs/plans/2026-02-27-batch-26-websocket-design.md
Normal file
128
docs/plans/2026-02-27-batch-26-websocket-design.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Batch 26 (WebSocket) Design
|
||||
|
||||
## Context Snapshot
|
||||
|
||||
- Batch: `26 - WebSocket`
|
||||
- Scope: `37 features`, `86 tests`
|
||||
- Dependencies: `16 (Client Core first half)`, `18 (Server Core)`
|
||||
- Go source: `golang/nats-server/server/websocket.go` (+ `websocket_test.go` for tests)
|
||||
- Current state:
|
||||
- Batch status is `pending`.
|
||||
- Batch is **not ready** (`batch ready` currently lists only batches 0, 1, 5, 8).
|
||||
- .NET websocket code is largely stubbed in `dotnet/src/ZB.MOM.NatsNet.Server/WebSocket/WebSocketTypes.cs`.
|
||||
- Multiple websocket-related stubs exist outside the websocket folder (`ClientConnection`, `NatsServer.Lifecycle`, `NatsServer.Listeners`).
|
||||
|
||||
## Goals
|
||||
|
||||
1. Port all 37 Batch 26 websocket features from `server/websocket.go` with behaviorally equivalent logic.
|
||||
2. Port and verify all 86 Batch 26 mapped tests with no fake/stub assertions.
|
||||
3. Remove websocket-specific stubs (`NotImplementedException`, placeholder comments, always-false flags) in runtime paths touched by this batch.
|
||||
4. Keep implementation idiomatic C# while preserving protocol correctness (frame parsing, masking, compression, upgrade validation, close/status handling).
|
||||
|
||||
## Non-Goals
|
||||
|
||||
1. Rewriting unrelated subsystems (MQTT, full leaf routing internals, non-websocket JetStream internals).
|
||||
2. Performance tuning beyond parity with Go logic and existing .NET architecture.
|
||||
3. Advancing blocked dependencies (Batches 16/18) inside this batch plan.
|
||||
|
||||
## Approaches Considered
|
||||
|
||||
### Approach A: Monolithic Port in `WebSocketTypes.cs`
|
||||
|
||||
- Description: Implement all websocket behavior inside the existing single file.
|
||||
- Pros: Minimal file churn.
|
||||
- Cons: Hard to review/test, encourages oversized methods, mixes protocol codec, HTTP upgrade, and server lifecycle logic in one place.
|
||||
|
||||
### Approach B (Recommended): Split by Concern with Partial Integration
|
||||
|
||||
- Description: Keep websocket-focused primitives in `WebSocket/` and wire server/client integration through partial class methods in `NatsServer` and `ClientConnection`.
|
||||
- Pros: Clear boundaries, easier per-feature verification, easier targeted tests, aligns with existing partial-class architecture in `NatsServer`.
|
||||
- Cons: More file edits and some type movement from current stubs.
|
||||
|
||||
### Approach C: Rely on `System.Net.WebSockets` High-Level Abstractions
|
||||
|
||||
- Description: Use framework websocket APIs for framing/handshake and adapt behavior.
|
||||
- Pros: Less low-level frame code.
|
||||
- Cons: Poor fit for NATS semantics (manual handshake headers, no-masking extension, explicit frame control, compression toggles, client/leaf modes). Higher behavior drift risk vs Go.
|
||||
|
||||
## Recommended Design (Approach B)
|
||||
|
||||
### 1) Component Boundaries
|
||||
|
||||
1. Frame/read-path primitives:
|
||||
- `WsReadInfo` state machine (`init`, `Read`, `ReadByte`, `NextCBuf`, `Decompress`, `Unmask`).
|
||||
- Static helpers for `WsGet`, `WsIsControlFrame`, frame-header creation/fill, masking utilities, close payload creation.
|
||||
2. Client websocket behavior:
|
||||
- `ClientConnection` websocket methods (`WsRead`, control frame handling/enqueue, close mapping, outbound collapse).
|
||||
- `IsWebSocket()` no longer hardcoded false once websocket state exists on connection.
|
||||
3. HTTP upgrade + option validation:
|
||||
- Handshake validation and response (`WsUpgrade`, header checks, accept key, compression negotiation, origin checks).
|
||||
- Options parsing/validation (`ValidateWebsocketOptions`, origin/header settings, auth override).
|
||||
4. Server lifecycle/listener integration:
|
||||
- Start/close websocket listener and include it in readiness checks.
|
||||
- Keep server INFO websocket connect URLs updated and propagated.
|
||||
|
||||
### 2) Data Flow
|
||||
|
||||
1. Upgrade flow:
|
||||
- HTTP request validation -> origin check -> extension negotiation -> connection hijack -> 101 response -> websocket context creation.
|
||||
2. Inbound frame flow:
|
||||
- Header decode -> mask enforcement -> payload size handling -> optional control-frame handling -> optional decompression -> payload slices returned for parser.
|
||||
3. Outbound frame flow:
|
||||
- Pending buffers -> optional compression -> fragmentation rules (browser/safari constraints) -> optional masking -> queued frames + close frame semantics.
|
||||
|
||||
### 3) Error Handling Model
|
||||
|
||||
1. Protocol violations map to websocket close frames with RFC status codes, then close/read termination behavior.
|
||||
2. Handshake failures return HTTP status + server-side error logging.
|
||||
3. Decompression limit violations map to payload errors (max payload).
|
||||
4. Any runtime branch that cannot be implemented due dependency/runtime gap is marked `deferred` with explicit reason, never stubbed.
|
||||
|
||||
### 4) File-Level Plan
|
||||
|
||||
Likely touched files:
|
||||
|
||||
- Source:
|
||||
- `dotnet/src/ZB.MOM.NatsNet.Server/WebSocket/WebSocketTypes.cs` (replace stubs/split responsibilities)
|
||||
- `dotnet/src/ZB.MOM.NatsNet.Server/WebSocket/WebSocketConstants.cs`
|
||||
- `dotnet/src/ZB.MOM.NatsNet.Server/ClientConnection.cs`
|
||||
- `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Listeners.cs`
|
||||
- `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Lifecycle.cs`
|
||||
- `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.Init.cs`
|
||||
- `dotnet/src/ZB.MOM.NatsNet.Server/NatsServer.cs`
|
||||
- Tests:
|
||||
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/WebSocketHandlerTests.Impltests.cs`
|
||||
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.Impltests.cs`
|
||||
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/NatsConsumerTests.Impltests.cs`
|
||||
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/LeafNodeHandlerTests.Impltests.cs`
|
||||
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests1.Impltests.cs`
|
||||
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/ConcurrencyTests2.Impltests.cs`
|
||||
- New backlog classes likely required by mapping:
|
||||
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/CoreBenchmarks.Impltests.cs`
|
||||
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/PublishBenchmarks.Impltests.cs`
|
||||
- `dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/LeafNodeProxyTests.Impltests.cs`
|
||||
|
||||
### 5) Test Strategy
|
||||
|
||||
1. Use strict ID-driven mapping from PortTracker for all 86 tests.
|
||||
2. For websocket functional tests, port assertions against frame semantics, handshake negotiation, header behavior, compression behavior, and outbound framing.
|
||||
3. For benchmark-mapped test IDs:
|
||||
- If deterministic behavioral assertions can be extracted, port as regular unit tests.
|
||||
- If benchmark-only and non-deterministic/perf-only, mark `n_a` or `deferred` with explicit reason and evidence.
|
||||
4. Add anti-stub checks to prevent placeholder tests passing as real.
|
||||
|
||||
### 6) Risks and Mitigations
|
||||
|
||||
1. Risk: Dependency batches 16/18 incomplete.
|
||||
- Mitigation: strict preflight gate, do not start batch until dependencies are complete.
|
||||
2. Risk: Silent stub regressions in broad ImplBacklog files.
|
||||
- Mitigation: mandatory grep-based stub scans and per-ID evidence before status updates.
|
||||
3. Risk: Frame/compression edge-case mismatch.
|
||||
- Mitigation: prioritize low-level frame tests first, then server/upgrade paths.
|
||||
4. Risk: Benchmarks misclassified as verified tests.
|
||||
- Mitigation: explicit benchmark decision gate (real deterministic test vs `n_a`/`deferred` with reason).
|
||||
|
||||
## Design Decision
|
||||
|
||||
Proceed with **Approach B** (split-by-concern websocket port with partial integration into `NatsServer`/`ClientConnection`), executed via a strict verification-first implementation plan.
|
||||
|
||||
Reference in New Issue
Block a user