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.
103 lines
5.1 KiB
Markdown
103 lines
5.1 KiB
Markdown
# 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:976–1037`) 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:2263–2575`:
|
||
|
||
```
|
||
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
|