Files
natsdotnet/gaps/core-server.md
2026-02-25 15:12:52 -05:00

34 KiB

Core Server — Gap Analysis

This file tracks what has and hasn't been ported from Go to .NET for the Core Server module. See stillmissing.md for the full LOC comparison across all modules.

LLM Instructions: How to Analyze This Category

Step 1: Read the Go Reference Files

Read each Go source file listed below. For every file:

  1. Extract all exported types (structs, interfaces, type aliases)
  2. Extract all exported methods on those types (receiver functions)
  3. Extract all exported standalone functions
  4. Note key constants, enums, and protocol states
  5. Note important unexported helpers that implement core logic (functions >20 lines)
  6. Pay attention to concurrency patterns (goroutines, mutexes, channels) — these map to different .NET patterns

Step 2: Read the .NET Implementation Files

Read all .cs files in the .NET directories listed below. For each Go symbol found in Step 1:

  1. Search for a matching type, method, or function in .NET
  2. If found, compare the behavior: does it handle the same edge cases? Same error paths?
  3. If partially implemented, note what's missing
  4. If not found, note it as MISSING

Step 3: Cross-Reference Tests

Compare Go test functions against .NET test methods:

  1. For each Go Test* function, check if a corresponding .NET [Fact] or [Theory] exists
  2. Note which test scenarios are covered and which are missing
  3. Check the parity DB (docs/test_parity.db) for existing mappings:
    sqlite3 docs/test_parity.db "SELECT go_test, dotnet_test, confidence FROM test_mappings tm JOIN go_tests gt ON tm.go_test_id=gt.rowid JOIN dotnet_tests dt ON tm.dotnet_test_id=dt.rowid WHERE gt.go_file LIKE '%PATTERN%'"
    

Step 4: Classify Each Item

Use these status values:

Status Meaning
PORTED Equivalent exists in .NET with matching behavior
PARTIAL .NET implementation exists but is incomplete (missing edge cases, error handling, or features)
MISSING No .NET equivalent found — needs to be ported
NOT_APPLICABLE Go-specific pattern that doesn't apply to .NET (build tags, platform-specific goroutine tricks, etc.)
DEFERRED Intentionally skipped for now (document why)

Step 5: Fill In the Gap Inventory

Add rows to the Gap Inventory table below. Group by Go source file. Include the Go file and line number so a porting LLM can jump directly to the reference implementation.

Key Porting Notes for Core Server

  • Go's client.go is the largest single file (~6,700 lines). It contains the readLoop/writeLoop goroutines, dynamic buffer sizing (512→65536), slow consumer detection, and per-client subscription tracking. The .NET equivalent should use async/await with System.IO.Pipelines.
  • Go's server.go manages listeners, accept loops, and shutdown coordination. Map goroutines to Task-based async patterns.
  • Go's opts.go handles both CLI flags and config file parsing (CLI overrides config). The .NET version separates this into Configuration/.
  • reload.go implements hot-reload by diffing old vs new config and applying deltas without restart.
  • Platform-specific files (service_windows.go, signal_windows.go, signal_wasm.go) may be NOT_APPLICABLE.

Go Reference Files (Source)

  • golang/nats-server/server/server.go — Server struct, startup lifecycle, listener management
  • golang/nats-server/server/client.go — Connection handling, readLoop/writeLoop, per-client state (~6,700 lines)
  • golang/nats-server/server/opts.go — Server options struct, CLI flag parsing, config file loading
  • golang/nats-server/server/reload.go — Hot reload on signal, config diffing
  • golang/nats-server/server/service.go — OS service/daemon management
  • golang/nats-server/server/signal.go — Signal handling (SIGHUP, SIGTERM, etc.)
  • golang/nats-server/main.go — Entry point

Go Reference Files (Tests)

  • golang/nats-server/server/server_test.go
  • golang/nats-server/server/client_test.go
  • golang/nats-server/server/opts_test.go
  • golang/nats-server/server/reload_test.go
  • golang/nats-server/server/signal_test.go
  • golang/nats-server/server/test_test.go (test helpers)

.NET Implementation Files (Source)

  • src/NATS.Server/NatsServer.cs — Server lifecycle
  • src/NATS.Server/NatsClient.cs — Per-connection client
  • src/NATS.Server/NatsOptions.cs — Server options
  • src/NATS.Server/ClientFlags.cs
  • src/NATS.Server/ClientKind.cs
  • src/NATS.Server/ClientClosedReason.cs
  • src/NATS.Server/ClientTraceInfo.cs
  • src/NATS.Server/ClosedState.cs
  • src/NATS.Server/INatsClient.cs
  • src/NATS.Server/InternalClient.cs
  • src/NATS.Server/ServerStats.cs
  • src/NATS.Server/SlowConsumerTracker.cs
  • src/NATS.Server/MqttOptions.cs
  • src/NATS.Server.Host/Program.cs — Entry point

.NET Implementation Files (Tests)

  • tests/NATS.Server.Tests/ (root-level test files)

Gap Inventory

Go Symbol Go File:Line Status .NET Equivalent Notes
golang/nats-server/main.go
main() main.go:97 PORTED src/NATS.Server.Host/Program.cs:1 CLI arg parsing, config load, server create, start, wait
usage() main.go:92 PARTIAL src/NATS.Server.Host/Program.cs No dedicated --help usage string; CLI flags are handled inline
golang/nats-server/server/server.go — Types
Info struct server.go:109 PORTED src/NATS.Server/Protocol/NatsProtocol.cs:39 (ServerInfo) Core fields ported; route/gateway/leafnode-specific fields are partial
Server struct server.go:169 PARTIAL src/NATS.Server/NatsServer.cs:31 Core fields ported (clients, accounts, opts, listener, shutdown). Missing: route pool tracking, gateway internals, OCSP monitors, proxied conns, rate limiting maps
stats struct server.go:402 PORTED src/NATS.Server/ServerStats.cs:6 All counters present
scStats struct server.go:413 PORTED src/NATS.Server/ServerStats.cs:18-25 Per-kind slow consumer counters present
staleStats struct server.go:421 PORTED src/NATS.Server/ServerStats.cs:26 Per-kind stale connection counters present
nodeInfo struct server.go:387 NOT_APPLICABLE JetStream cluster-specific; tracked in JetStream module
Ports struct server.go:4236 MISSING Not implemented; no /ports output support
Compression constants server.go:437-446 MISSING S2 compression mode constants not defined in core server
CompressionOpts struct server.go:97 (opts.go) MISSING No compression options type in .NET
golang/nats-server/server/server.go — Exported Server Methods
NewServer() server.go:716 PORTED src/NATS.Server/NatsServer.cs constructor Options validation, NKey identity, info setup
New() (deprecated) server.go:698 NOT_APPLICABLE Deprecated wrapper
NewServerFromConfig() server.go:703 PORTED src/NATS.Server.Host/Program.cs:20-22 Config file processing then new server
(s) Start() server.go:2263 PORTED src/NATS.Server/NatsServer.cs:502 (StartAsync) Listener, accept loop, subsystem startup. Async in .NET
(s) Shutdown() server.go:2583 PORTED src/NATS.Server/NatsServer.cs:163 (ShutdownAsync) Client disconnect, listener close, subsystem teardown
(s) WaitForShutdown() server.go:2775 PORTED src/NATS.Server/NatsServer.cs:150 Blocks until shutdown complete
(s) AcceptLoop() server.go:2780 PORTED src/NATS.Server/NatsServer.cs:502 (inline in StartAsync) Accept loop is part of StartAsync
(s) ReadyForConnections() server.go:4023 PORTED src/NATS.Server/NatsServer.cs:148 (WaitForReadyAsync) Async TaskCompletionSource-based
(s) Running() server.go:1695 PORTED src/NATS.Server/NatsServer.cs:108 (IsShuttingDown inverted) Derived from shutdown flag
(s) ID() server.go:4036 PORTED src/NATS.Server/NatsServer.cs:101 (ServerId)
(s) Name() server.go:4046 PORTED src/NATS.Server/NatsServer.cs:102 (ServerName)
(s) NodeName() server.go:4041 PORTED src/NATS.Server/NatsServer.cs:102 Same as ServerName
(s) ClusterName() server.go:1017 PARTIAL src/NATS.Server/NatsServer.cs:110 (ClusterListen) Only listen endpoint; no cluster name getter
(s) ClientURL() server.go:1086 MISSING No dedicated method to return client connect URL
(s) WebsocketURL() server.go:1100 MISSING No dedicated websocket URL getter
(s) NumClients() server.go:3810 PORTED src/NATS.Server/NatsServer.cs:103 (ClientCount)
(s) NumRoutes() server.go:3773 PARTIAL src/NATS.Server/ServerStats.cs:14 (Routes field) Stats counter exists; no lock-safe method like Go
(s) NumRemotes() server.go:3790 MISSING
(s) NumLeafNodes() server.go:3803 PARTIAL src/NATS.Server/ServerStats.cs:16 (Leafs field) Stats counter; no lock-safe count method
(s) NumSubscriptions() server.go:3836 MISSING No aggregated subscription count method
(s) NumSlowConsumers() server.go:3855 PORTED src/NATS.Server/ServerStats.cs:12 Direct field access
(s) NumSlowConsumersClients() server.go:3865 PORTED src/NATS.Server/ServerStats.cs:18
(s) NumSlowConsumersRoutes() server.go:3870 PORTED src/NATS.Server/ServerStats.cs:19
(s) NumSlowConsumersGateways() server.go:3875 PORTED src/NATS.Server/ServerStats.cs:21
(s) NumSlowConsumersLeafs() server.go:3880 PORTED src/NATS.Server/ServerStats.cs:20
(s) NumStalledClients() server.go:3860 PORTED src/NATS.Server/ServerStats.cs:17 (Stalls)
(s) NumStaleConnections() server.go:3885 PORTED src/NATS.Server/ServerStats.cs:13
(s) NumStaleConnectionsClients() server.go:3890 PORTED src/NATS.Server/ServerStats.cs:22
(s) NumStaleConnectionsRoutes() server.go:3895 PORTED src/NATS.Server/ServerStats.cs:23
(s) NumStaleConnectionsGateways() server.go:3900 PORTED src/NATS.Server/ServerStats.cs:24
(s) NumStaleConnectionsLeafs() server.go:3905 PORTED src/NATS.Server/ServerStats.cs:25
(s) GetClient() server.go:3817 PORTED src/NATS.Server/NatsServer.cs:119 (GetClients enumerable) Enumerable, not by-ID lookup
(s) GetLeafNode() server.go:3829 MISSING No leaf node by-CID lookup
(s) ConfigTime() server.go:3910 MISSING No config time tracking exposed
(s) Addr() server.go:3917 PARTIAL src/NATS.Server/NatsServer.cs:104 (Port) Port exposed but not full net.Addr
(s) MonitorAddr() server.go:3927 MISSING Monitoring managed by MonitorServer separately
(s) ClusterAddr() server.go:3937 PARTIAL src/NATS.Server/NatsServer.cs:110 (ClusterListen string) String, not TCPAddr
(s) ProfilerAddr() server.go:3947 MISSING No profiler address getter
(s) ActivePeers() server.go:1577 MISSING Cluster peer enumeration not in core
(s) NumActiveAccounts() server.go:1716 MISSING No active account count method
(s) NumLoadedAccounts() server.go:1744 PARTIAL src/NATS.Server/NatsServer.cs:123 (GetAccounts) Enumerable, no count method
(s) LookupOrRegisterAccount() server.go:1749 PORTED src/NATS.Server/NatsServer.cs:1260 (GetOrCreateAccount)
(s) RegisterAccount() server.go:1762 PORTED src/NATS.Server/NatsServer.cs:1260 Via GetOrCreateAccount
(s) SetSystemAccount() server.go:1775 PORTED src/NATS.Server/NatsServer.cs constructor Set during construction
(s) SystemAccount() server.go:1798 PORTED src/NATS.Server/NatsServer.cs:105
(s) GlobalAccount() server.go:1804 PORTED src/NATS.Server/NatsServer.cs:50 (_globalAccount)
(s) LookupAccount() server.go:2106 PORTED src/NATS.Server/NatsServer.cs:1260 Via GetOrCreateAccount
(s) StartProfiler() server.go:2941 MISSING No built-in profiler; .NET uses dotnet-trace/counters
(s) StartMonitoring() server.go:3014 PORTED src/NATS.Server/Monitoring/MonitorServer.cs Separate monitoring server class
(s) StartHTTPMonitoring() server.go:3003 PORTED src/NATS.Server/Monitoring/MonitorServer.cs:140
(s) StartHTTPSMonitoring() server.go:3009 PORTED src/NATS.Server/Monitoring/MonitorServer.cs HTTPS variant via options
(s) HTTPHandler() server.go:3207 PARTIAL src/NATS.Server/Monitoring/MonitorServer.cs ASP.NET Kestrel handles routing, not an http.Handler
(s) InProcessConn() server.go:2876 MISSING No in-process connection support
(s) LameDuckShutdown() server.go:4421 PORTED src/NATS.Server/NatsServer.cs:239 (LameDuckShutdownAsync) Full LDM with grace period and duration
(s) DisconnectClientByID() server.go:4742 MISSING No per-client disconnect by ID
(s) LDMClientByID() server.go:4757 MISSING No per-client lame duck by ID
(s) PortsInfo() server.go:4247 MISSING No Ports struct output
(s) String() server.go:4050 MISSING No server string representation
PrintAndDie() server.go:1664 NOT_APPLICABLE .NET uses exceptions/logging
PrintServerAndExit() server.go:1670 NOT_APPLICABLE .NET uses --version flag differently
ProcessCommandLineArgs() server.go:1678 PORTED src/NATS.Server.Host/Program.cs:25-137 Inline switch-based CLI parsing
golang/nats-server/server/server.go — Key Unexported Helpers
(s) createClient() server.go:3245 PORTED src/NATS.Server/NatsServer.cs:666 (AcceptClientAsync) Creates NatsClient, runs it
(s) createInternalClient() server.go:1925 PORTED src/NATS.Server/InternalClient.cs:29 InternalClient class
(s) createInternalSystemClient() server.go:1910 PORTED src/NATS.Server/NatsServer.cs:377 System internal client creation
(s) acceptConnections() server.go:2889 PORTED src/NATS.Server/NatsServer.cs:502 (StartAsync accept loop) Inline in StartAsync
(s) removeClient() server.go:3708 PORTED src/NATS.Server/NatsServer.cs RemoveClient() via IMessageRouter
(s) saveClosedClient() server.go:3561 PORTED src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs ClosedConnectionRingBuffer
(s) configureAccounts() server.go:1230 PARTIAL src/NATS.Server/NatsServer.cs constructor Basic account setup; no multi-account import/export wiring
(s) setInfoHostPort() server.go:2921 PORTED src/NATS.Server/NatsServer.cs:496 (BuildCachedInfo)
(s) lameDuckMode() server.go:4428 PORTED src/NATS.Server/NatsServer.cs:239 (LameDuckShutdownAsync) Async version
(s) handleSignals() server.go (signal.go:37) PORTED src/NATS.Server/NatsServer.cs:320 (HandleSignals) Uses PosixSignalRegistration on .NET
(s) logPorts() server.go:4332 PARTIAL src/NATS.Server/NatsServer.cs Logs port at startup; no ports file
(s) startGoRoutine() server.go:4070 NOT_APPLICABLE .NET uses Task.Run; no goroutine tracking needed
(s) readyForConnections() server.go:3956 PORTED src/NATS.Server/NatsServer.cs:148 (WaitForReadyAsync)
(s) getOpts() server.go:1206 PORTED src/NATS.Server/NatsServer.cs:33 (_options field) Direct field access
(s) isRunning() server.go:1700 PORTED src/NATS.Server/NatsServer.cs:108 Inverted IsShuttingDown
(s) isShuttingDown() server.go:2577 PORTED src/NATS.Server/NatsServer.cs:108 (IsShuttingDown)
(s) updateServerINFOAndSendINFOToClients() server.go:3622 MISSING No dynamic INFO update broadcast to existing clients
(s) getConnectURLs() server.go:4120 MISSING No connect URL resolution for clustering
(s) getNonLocalIPsIfHostIsIPAny() server.go:4159 MISSING IP enumeration for advertise not implemented
(s) portFile() server.go:4307 MISSING No ports file creation
(s) logPid() server.go:1704 PARTIAL src/NATS.Server/NatsServer.cs PID file support present in options but write logic minimal
validateAndNormalizeCompressionOption() server.go:466 MISSING No compression option validation
selectCompressionMode() server.go:559 MISSING No compression mode negotiation
selectS2AutoModeBasedOnRTT() server.go:618 MISSING No RTT-based auto compression
needsCompression() server.go:549 MISSING
s2WriterOptions() server.go:678 MISSING
golang/nats-server/server/client.go — Types
client struct client.go:259 PORTED src/NATS.Server/NatsClient.cs:35 Core fields: cid, kind, subs, opts, flags, stats. Missing: route/gw/leaf/mqtt sub-structs, perms cache, nonce, pubKey
ClosedState enum client.go:188 PORTED src/NATS.Server/ClosedState.cs:14 Full enum parity with all values
ClientOpts struct client.go:661 PORTED src/NATS.Server/Protocol/ClientOptions.cs Echo, Verbose, Pedantic, TLS, JWT, NKey, Headers, NoResponders
clientFlag type client.go:132 PORTED src/NATS.Server/ClientFlags.cs:9 Core flags present; missing some (infoReceived, noReconnect, expectConnect, compressionNegotiated, didTLSFirst)
WriteTimeoutPolicy client.go:239 PORTED src/NATS.Server/NatsClient.cs:975 Close and TcpFlush policies
subscription struct client.go:631 PORTED src/NATS.Server/Subscriptions/Subscription.cs Subject, queue, sid, client, max, messageCount
outbound struct client.go:349 PARTIAL src/NATS.Server/NatsClient.cs:47-48 Channel-based outbound; missing: net.Buffers, sync.Cond, S2 writer, stall channel
readCache struct client.go:485 MISSING No per-client subject lookup cache
perAccountCache struct client.go:541 MISSING No per-account L1 cache for routes/gateways
pinfo struct client.go:343 PORTED src/NATS.Server/NatsClient.cs:99 (_pingsOut) Simplified: no timer struct, uses PeriodicTimer
permissions struct client.go:430 PORTED src/NATS.Server/Auth/ClientPermissions.cs Pub/sub allow/deny; missing: pcache (permission cache)
routeTarget struct client.go:458 MISSING Route message targeting structure
msgDeny struct client.go:451 MISSING Deny-based message filtering cache
resp struct client.go:442 MISSING Dynamic response permission tracking
CLIENT/ROUTER/GATEWAY/SYSTEM/LEAF/JETSTREAM/ACCOUNT constants client.go:44-60 PORTED src/NATS.Server/ClientKind.cs:8 All client kinds present
isInternalClient() client.go:63 PORTED src/NATS.Server/ClientKind.cs:20 (IsInternal extension)
NON_CLIENT/NATS/MQTT/WS constants client.go:70-79 PARTIAL src/NATS.Server/NatsClient.cs:107 (IsWebSocket) WebSocket bool exists; no explicit MQTT/NATS/NON_CLIENT sub-type enum
ClientProtoZero/ClientProtoInfo client.go:82-88 MISSING Client protocol version constants not defined
golang/nats-server/server/client.go — Exported Methods
(c) String() client.go:547 MISSING No formatted string representation
(c) GetNonce() client.go:557 PARTIAL src/NATS.Server/NatsClient.cs:43 (_nonce field) Field exists but no public getter
(c) GetName() client.go:565 PARTIAL src/NATS.Server/NatsClient.cs:58 (ClientOpts?.Name) Via ClientOpts property
(c) GetOpts() client.go:573 PORTED src/NATS.Server/NatsClient.cs:58 (ClientOpts)
(c) GetTLSConnectionState() client.go:579 PORTED src/NATS.Server/NatsClient.cs:110 (TlsState) TlsConnectionState type
(c) RemoteAddress() client.go:822 PORTED src/NATS.Server/NatsClient.cs:85-86 (RemoteIp, RemotePort) Separate IP and port properties
(c) Kind() client.go:844 PORTED src/NATS.Server/NatsClient.cs:57 (Kind property)
(c) RegisterUser() client.go:981 MISSING User registration on client not implemented
(c) RegisterNkeyUser() client.go:1018 MISSING NKey user registration on client not implemented
(c) Account() client.go:6204 PORTED src/NATS.Server/NatsClient.cs:61 (Account property)
(c) Error/Errorf/Debugf/Noticef/Tracef/Warnf client.go:6586-6610 PORTED src/NATS.Server/NatsClient.cs:52 (_logger) Uses ILogger structured logging
(c) RateLimitErrorf/Warnf/Debugf client.go:6610-6650 MISSING No rate-limited logging per client
golang/nats-server/server/client.go — Key Unexported Methods
(c) initClient() client.go:704 PORTED src/NATS.Server/NatsClient.cs:116 (constructor) CID assignment, outbound setup, subs map, trace level
(c) readLoop() client.go:1358 PORTED src/NATS.Server/NatsClient.cs:296 (FillPipeAsync + ProcessCommandsAsync) System.IO.Pipelines instead of goroutine + byte buffer
(c) writeLoop() client.go:1274 PORTED src/NATS.Server/NatsClient.cs:785 (RunWriteLoopAsync) Channel-based async write loop
(c) processConnect() client.go:2167 PORTED src/NATS.Server/NatsClient.cs:450 (ProcessConnectAsync) JSON deserialization, auth, account binding
(c) processPub() client.go:2822 PORTED src/NATS.Server/NatsClient.cs:627 (ProcessPub) Subject validation, permission check, router dispatch
(c) processHeaderPub() client.go:2745 PORTED src/NATS.Server/NatsClient.cs:660 HPUB handling with header size split
(c) parseSub() / processSub() client.go:2898/2927 PORTED src/NATS.Server/NatsClient.cs:560 (ProcessSub) Permission check, limit check, sublist insert
(c) processUnsub() client.go:3366 PORTED src/NATS.Server/NatsClient.cs:605 (ProcessUnsub) Max messages auto-unsub, sublist remove
(c) processPing() client.go:2628 PORTED src/NATS.Server/NatsClient.cs:414 (Pong case in DispatchCommandAsync)
(c) processPong() client.go:2680 PORTED src/NATS.Server/NatsClient.cs:419-428 RTT calculation, pingsOut reset
(c) queueOutbound() client.go:2448 PORTED src/NATS.Server/NatsClient.cs:140 (QueueOutbound) Channel-based with pending bytes tracking
(c) flushOutbound() client.go:1618 PORTED src/NATS.Server/NatsClient.cs:785 (RunWriteLoopAsync drain) Inline in write loop
(c) flushSignal() client.go:1996 PORTED src/NATS.Server/NatsClient.cs:197 (SignalFlushPending) Interlocked counter
(c) sendPing() client.go:2577 PORTED src/NATS.Server/NatsClient.cs:888 RTT start tracking, write PING
(c) sendPong() client.go:2540 PORTED src/NATS.Server/NatsClient.cs:397 Write PONG bytes
(c) sendRTTPing() client.go:2548 PORTED src/NATS.Server/NatsClient.cs:887 RTT start tick recording
(c) sendErr() client.go:2608 PORTED src/NATS.Server/NatsClient.cs:779 (SendErr)
(c) sendOK() client.go:2619 PORTED src/NATS.Server/NatsClient.cs:344 (OkBytes write on Verbose)
(c) processPingTimer() client.go:5537 PORTED src/NATS.Server/NatsClient.cs:853 (RunPingTimerAsync) PeriodicTimer-based, stale detection
(c) closeConnection() client.go:5868 PORTED src/NATS.Server/NatsClient.cs:834 (CloseWithReasonAsync) Async close with reason
(c) markConnAsClosed() client.go:1906 PORTED src/NATS.Server/NatsClient.cs:902 (MarkClosed) Skip-flush flag, reason tracking
(c) deliverMsg() client.go:3620 PARTIAL src/NATS.Server/NatsClient.cs:692 (SendMessage) Basic MSG/HMSG delivery. Missing: echo check, MQTT interop, GW reply mapping, stall wait
(c) processInboundMsg() client.go:4139 PARTIAL src/NATS.Server/NatsServer.cs:938 (ProcessMessage) Routes to local subs; missing: route/gateway/leaf-specific inbound handlers
(c) processInboundClientMsg() client.go:4166 PARTIAL src/NATS.Server/NatsServer.cs:938 Core pub path ported; missing: subject mapping, GW reply mapping, NRG prefix check
(c) processMsgResults() client.go:4932 PARTIAL src/NATS.Server/NatsServer.cs:938-1088 Queue group selection ported; missing: route forwarding, gateway forwarding, queue name collection
(c) stalledWait() client.go:3575 PORTED src/NATS.Server/NatsClient.cs:1017 (StallGate class) SemaphoreSlim-based stall gate
(c) flushClients() client.go:1324 MISSING Post-readLoop batch flush of producer clients (pcd) not implemented
(c) handleWriteTimeout() client.go:1842 PARTIAL src/NATS.Server/NatsClient.cs:807-813 Slow consumer detection on timeout; missing: retry policy for routes
(c) msgHeader() client.go:3534 PORTED src/NATS.Server/NatsClient.cs:692 (SendMessage) Inline MSG line construction
(c) msgHeaderForRouteOrLeaf() client.go:3447 MISSING RMSG header construction for routes/leafnodes
(c) setPermissions() client.go:1055 PORTED src/NATS.Server/NatsClient.cs:477 Via ClientPermissions.Build(authResult.Permissions)
(c) pubAllowed() client.go:4052 PORTED src/NATS.Server/Auth/ClientPermissions.cs IsPublishAllowed()
(c) canSubscribe() client.go:3230 PORTED src/NATS.Server/Auth/ClientPermissions.cs IsSubscribeAllowed()
(c) setExpiration() client.go:1243 PORTED src/NATS.Server/NatsClient.cs:534-557 Auth expiry timer via Task.Delay
(c) authTimeout() client.go:2383 PORTED src/NATS.Server/NatsClient.cs:238-253 Auth timeout Task
(c) authViolation() client.go:2398 PORTED src/NATS.Server/NatsClient.cs:471-473 Auth violation error + close
(c) maxPayloadViolation() client.go:2440 PORTED src/NATS.Server/NatsClient.cs:633-639 Max payload check and close
(c) maxSubsExceeded() client.go:2433 PORTED src/NATS.Server/NatsClient.cs:571-576
(c) maxConnExceeded() client.go:2428 PARTIAL src/NATS.Server/NatsServer.cs:610 Server-level max conn check; no per-client method
(c) subsAtLimit() client.go:900 PORTED src/NATS.Server/NatsClient.cs:571 MaxSubs check in ProcessSub
(c) applyAccountLimits() client.go:923 PARTIAL src/NATS.Server/NatsClient.cs:488-494 Account client count check; missing: maxPayload/maxSubs per-account override
(c) registerWithAccount() client.go:854 PORTED src/NATS.Server/NatsClient.cs:480-494 Account binding during connect
(c) setTraceLevel() client.go:695 PORTED src/NATS.Server/NatsClient.cs:68 (SetTraceMode)
(c) clientType() client.go:599 PARTIAL src/NATS.Server/NatsClient.cs:107 (IsWebSocket) Bool for WS; no MQTT/NATS sub-type dispatch
(c) addShadowSubscriptions() client.go:3057 MISSING Account import shadow subscription system
(c) pruneDenyCache() / prunePubPermsCache() / pruneReplyPerms() client.go:4007-4019 MISSING Permission cache pruning
(c) trackRemoteReply() / pruneRemoteTracking() client.go:3915/3956 MISSING Reply tracking for latency
(c) loadMsgDenyFilter() client.go:1265 MISSING Message-level deny filter loading
(c) generateClientInfoJSON() client.go:2589 PARTIAL src/NATS.Server/NatsClient.cs:674 (SendInfo) Generates INFO JSON; missing: per-client IP inclusion, connect_urls
(c) updateS2AutoCompressionLevel() client.go:2723 MISSING RTT-based compression adjustment
(c) addToPCD() client.go:3905 MISSING Producer client data batch tracking
(c) collapsePtoNB() client.go:1608 NOT_APPLICABLE Go-specific net.Buffers collapse; .NET uses Channel
nbPoolGet/nbPoolPut client.go:393-423 NOT_APPLICABLE Go-specific sync.Pool; .NET uses ArrayPool/MemoryPool
golang/nats-server/server/opts.go — Types
Options struct opts.go:326 PORTED src/NATS.Server/NatsOptions.cs:8 Core fields present. Missing: DontListen, NoLog, NoSigs, ProxyRequired, CustomAuth, CheckConfig, JetStreamTpm, resolverPreloads
ClusterOpts struct opts.go:64 PORTED src/NATS.Server/Configuration/ClusterOptions.cs Core fields; missing: compression, pool size, pinned accounts, write timeout policy
GatewayOpts struct opts.go:114 PORTED src/NATS.Server/Configuration/GatewayOptions.cs Core fields; missing: compression, reject unknown, send qsubs buf
RemoteGatewayOpts struct opts.go:145 PORTED src/NATS.Server/Configuration/GatewayOptions.cs:27
LeafNodeOpts struct opts.go:154 PORTED src/NATS.Server/Configuration/LeafNodeOptions.cs:22 Core fields; missing: compression, isolate subjects, min version
RemoteLeafOpts struct opts.go:218 PORTED src/NATS.Server/Configuration/LeafNodeOptions.cs:7
WebsocketOpts struct opts.go:518 PORTED src/NATS.Server/NatsOptions.cs:138 (WebSocketOptions)
MQTTOpts struct opts.go:613 PORTED src/NATS.Server/MqttOptions.cs:8
TLSConfigOpts struct opts.go:790 PARTIAL src/NATS.Server/NatsOptions.cs:96-107 Flat TLS fields on NatsOptions; no TLSConfigOpts class
OCSPConfig struct opts.go:823 PARTIAL src/NATS.Server/NatsOptions.cs:110 (OcspConfig) Basic config; missing: full OCSP mode selection
AuthCallout struct opts.go:308 MISSING External auth callout configuration
JSLimitOpts struct opts.go:289 MISSING Per-account JetStream limit options
JSTpmOpts struct opts.go:300 NOT_APPLICABLE TPM (Trusted Platform Module) not applicable to .NET
ProxiesConfig struct opts.go:832 MISSING Proxy configuration
PinnedCertSet type opts.go:59 PORTED src/NATS.Server/NatsOptions.cs:106 (TlsPinnedCerts HashSet)
golang/nats-server/server/opts.go — Exported Functions
ProcessConfigFile() opts.go:870 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:15 Full config file parsing
ConfigureOptions() opts.go:6023 PORTED src/NATS.Server.Host/Program.cs:25-137 CLI flag parsing inline
MergeOptions() opts.go:5714 PORTED src/NATS.Server/Configuration/ConfigReloader.cs MergeCliOverrides
RoutesFromStr() opts.go:5797 MISSING Parse comma-separated route URLs
GenTLSConfig() opts.go:5633 PARTIAL src/NATS.Server/Tls/ TLS setup exists but not as a standalone GenTLSConfig function
PrintTLSHelpAndDie() opts.go:4886 NOT_APPLICABLE Go-specific CLI help
NoErrOnUnknownFields() opts.go:50 MISSING Config parsing error control
golang/nats-server/server/opts.go — Exported Options Methods
(o) Clone() opts.go:715 MISSING Deep copy of Options not implemented
(o) ProcessConfigFile() opts.go:974 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:17
(o) ProcessConfigString() opts.go:990 MISSING Parse config from string
(o) ConfigDigest() opts.go:1000 MISSING Config file digest
golang/nats-server/server/reload.go
FlagSnapshot var reload.go:36 PORTED src/NATS.Server/NatsServer.cs:44-46 (_cliSnapshot, _cliFlags)
option interface reload.go:43 PORTED src/NATS.Server/Configuration/IConfigChange.cs IConfigChange with Apply, IsLoggingChange, etc.
noopOption / loggingOption / traceLevelOption reload.go:77-129 PORTED src/NATS.Server/Configuration/IConfigChange.cs:42 (ConfigChange) Simplified: single ConfigChange class with flags
traceOption / debugOption / logfileOption / etc. reload.go:131-200+ PARTIAL src/NATS.Server/Configuration/ConfigReloader.cs Diff-based; individual option types not replicated, uses property comparison
(s) Reload() reload.go:1090 PORTED src/NATS.Server/NatsServer.cs:1623 (ReloadConfig) Reads config file, diffs, applies
(s) ReloadOptions() reload.go:1111 PORTED src/NATS.Server/NatsServer.cs:1633 (ReloadConfigCore) Config diff and apply
reloadContext struct reload.go:38 MISSING Reload context for cluster perms
applyBoolFlags() reload.go:1185 PARTIAL src/NATS.Server/Configuration/ConfigReloader.cs MergeCliOverrides CLI override merge exists; no bool flag reflection
golang/nats-server/server/signal.go
SetProcessName() signal.go:32 NOT_APPLICABLE Unix-specific process name
(s) handleSignals() signal.go:37 PORTED src/NATS.Server/NatsServer.cs:320 (HandleSignals) PosixSignalRegistration for SIGINT/SIGTERM/SIGHUP/SIGUSR2
ProcessSignal() signal.go:89 NOT_APPLICABLE Unix-specific kill/pgrep signal dispatch
CommandToSignal() signal.go:145 NOT_APPLICABLE Unix syscall.Signal mapping
resolvePids() signal.go:165 NOT_APPLICABLE Unix-specific pgrep
golang/nats-server/server/service.go
Run() service.go:20 PORTED src/NATS.Server.Host/Program.cs:235 StartAsync + WaitForShutdown
isWindowsService() service.go:26 NOT_APPLICABLE Build-tag guarded; not relevant for .NET

Summary Counts

Status Count
PORTED 123
PARTIAL 30
MISSING 55
NOT_APPLICABLE 14
DEFERRED 0
Total 222

Keeping This File Updated

After porting work is completed:

  1. Update status: Change MISSING → PORTED or PARTIAL → PORTED for each item completed
  2. Add .NET path: Fill in the ".NET Equivalent" column with the actual file:line
  3. Re-count LOC: Update the LOC numbers in stillmissing.md:
    # Re-count .NET source LOC for this module
    find src/NATS.Server/ -maxdepth 1 -name '*.cs' -type f -exec cat {} + | wc -l
    # Re-count .NET test LOC for this module
    find tests/NATS.Server.Tests/ -maxdepth 1 -name '*.cs' -type f -exec cat {} + | wc -l
    
  4. Add a changelog entry below with date and summary of what was ported
  5. Update the parity DB if new test mappings were created:
    sqlite3 docs/test_parity.db "INSERT INTO test_mappings (go_test_id, dotnet_test_id, confidence, notes) VALUES (?, ?, 'manual', 'ported in YYYY-MM-DD session')"
    

Change Log

Date Change By
2026-02-25 File created with LLM analysis instructions auto
2026-02-25 Gap inventory populated: 222 symbols analyzed (123 PORTED, 30 PARTIAL, 55 MISSING, 14 NOT_APPLICABLE) across server.go, client.go, opts.go, reload.go, signal.go, service.go, main.go claude-opus