Files
natsnet/docs/plans/2026-03-01-server-boot-parity-design.md
Joseph Doherty ca8297d0ad docs: add server boot parity design
Design for wiring NatsServer.Start() to call all subsystem startup
methods matching Go's Server.Start() sequence, enabling a fully
booting server that accepts client connections.
2026-03-01 14:47:50 -05:00

103 lines
5.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Server Boot Parity Design
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers-extended-cc:executing-plans to implement this plan task-by-task.
**Goal:** Wire up `NatsServer.Start()` to call all subsystem startup methods in the same order as Go's `Server.Start()`, enabling a fully booting server that accepts client connections.
**Architecture:** The .NET port already has every subsystem startup method implemented (`AcceptLoop`, `StartMonitoring`, `EnableJetStream`, `StartRouting`, `StartGateways`, `StartLeafNodeAcceptLoop`, `StartWebsocketServer`, etc.). The only gap is that `Start()` (in `NatsServer.Init.cs:9761037`) stops after system account setup instead of continuing through the full startup sequence. The fix is wiring — calling existing methods in the correct order — plus 3 trivial no-op stubs for missing minor methods and guarding the MQTT `NotImplementedException`.
**Tech Stack:** .NET 10, C# latest, xUnit, NATS.Client.Core (for validation test)
---
## Problem Statement
The .NET `Start()` method currently:
1. Logs version/name info
2. Sets `_running = 1`
3. Enables leafnode flag
4. Writes PID file
5. Sets up system account
6. Starts OCSP response cache
7. Signals `_startupComplete` and logs "Server is ready"
It is missing ~15 subsystem calls that Go's `Start()` makes between steps 5 and 7.
## Design
### 1. Complete `Start()` Body
Insert the following calls in `NatsServer.Init.cs` between the system account setup and the "Server is ready" log, matching Go `server.go:22632575`:
```
CheckAuthForWarnings() -- new no-op stub
StartRateLimitLogExpiration() -- exists in Lifecycle.cs
StartProfiler() if ProfPort != 0 -- exists (stub) in Listeners.cs
Log config file info -- opts.ConfigFile notice
Log trusted operators -- opts.TrustedOperators loop
StartMonitoring() -- exists in Listeners.cs
AccountResolver.Start() if resolver != null -- exists
StartGWReplyMapExpiration() -- exists in Gateways.ReplyMap.cs
EnableJetStream(cfg) if opts.JetStream -- exists in JetStreamCore.cs
else: check accounts for JS limits -- exists (EnableJetStreamAccounts pattern)
StartDelayedApiResponder() -- new no-op stub
StartOCSPMonitoring() -- exists in Ocsp.cs
InitOCSPResponseCache() -- exists (StartOCSPResponseCache)
StartGateways() if Gateway.Port != 0 -- exists in Gateways.ConfigAndStartup.cs
StartWebsocketServer() if Websocket.Port != 0 -- exists in WebSocket.cs
StartLeafNodeAcceptLoop() if LeafNode.Port != 0 -- exists in LeafNodes.ConfigAndConnect.cs
SolicitLeafNodeRemotes() if remotes.Count > 0 -- exists in LeafNodes.ConfigAndConnect.cs
StartMqtt() if MQTT.Port != 0 -- guard NotImplementedException
StartRouting() if Cluster.Port != 0 -- exists in Routes.Connections.cs
LogPorts() if PortsFileDir != empty -- new no-op stub
Signal _startupComplete -- move to here (from current position)
AcceptLoop() if !DontListen -- exists in Listeners.cs
StartOCSPResponseCache() -- exists (move to after AcceptLoop)
Noticef("Server is ready") -- move to end
```
### 2. New Method Stubs
**`CheckAuthForWarnings()`** — `NatsServer.Auth.cs`
- No-op. In Go this logs warnings about insecure auth configs. Can be implemented later.
**`StartDelayedApiResponder()`** — `NatsServer.JetStreamCore.cs`
- Starts a background task that will process delayed JetStream API responses.
- Initial implementation: no-op goroutine that exits when `_quitCts` cancels.
**`LogPorts()`** — `NatsServer.Init.cs`
- No-op. Writes ports info to file when `PortsFileDir` configured. Minor utility.
### 3. MQTT Guard
Change `MqttServerExtensions.StartMqtt()` from throwing `NotImplementedException` to logging a warning and returning. This prevents `Start()` from crashing when MQTT port is configured.
### 4. Validation Test
New test file: `dotnet/tests/ZB.MOM.NatsNet.Server.IntegrationTests/ServerBootTests.cs`
Test: `ServerBoot_AcceptsClientConnection_ShouldSucceed`
- Creates server with ephemeral port, JetStream enabled, temp store dir
- Calls `Start()`
- Connects with `NATS.Client.Core.NatsConnection`
- Publishes to `test.subject` and verifies subscribe receives message
- Calls `Shutdown()`
### 5. Files Changed
| File | Change |
|------|--------|
| `NatsServer.Init.cs` | Complete `Start()` body, add `LogPorts()` stub |
| `NatsServer.Auth.cs` | Add `CheckAuthForWarnings()` stub |
| `NatsServer.JetStreamCore.cs` | Add `StartDelayedApiResponder()` stub |
| `Mqtt/MqttHandler.cs` | Guard `StartMqtt()` to not throw |
| `ServerBootTests.cs` | New integration test |
### 6. Success Criteria
- `dotnet build` passes with 0 errors
- Existing unit tests still pass (2659 pass, 53 skip)
- Existing integration tests still pass (113 pass, 854 skip, 0 fail)
- New `ServerBoot_AcceptsClientConnection_ShouldSucceed` test passes
- Server logs show full startup sequence matching Go's output pattern