Captures the design for resolving the two remaining high-priority gaps in differences.md: config file parsing and SIGHUP hot reload.
7.0 KiB
7.0 KiB
Config File Parsing & Hot Reload Design
Resolves the two remaining high-priority gaps in differences.md.
Goals
- Port the Go NATS config file parser (
conf/lex.go+conf/parse.go) to .NET - Map parsed config to existing + new
NatsOptionsfields (single-server scope) - Implement SIGHUP hot reload matching Go's reloadable option set
- Add unit tests for lexer, parser, config processor, and reload
Architecture
Config File
→ NatsConfLexer (state-machine tokenizer)
→ NatsConfParser (builds Dictionary<string, object?>)
→ ConfigProcessor.Apply(dict, NatsOptions)
→ NatsOptions populated
SIGHUP
→ NatsServer.ReloadConfig()
→ Re-parse config file
→ Merge with CLI flag snapshot
→ ConfigReloader.Diff(old, new) → IConfigChange[]
→ Validate (reject non-reloadable)
→ Apply each change to running server
Component 1: Lexer (NatsConfLexer.cs)
Direct port of Go conf/lex.go (~1320 lines Go → ~400 lines C#).
State-machine tokenizer producing typed tokens:
Key,String,Bool,Integer,Float,DateTimeArrayStart/ArrayEnd,MapStart/MapEndVariable,Include,Comment,EOF,Error
Supported syntax:
- Key separators:
=,:, or whitespace - Comments:
#and// - Strings:
"double",'single', raw (unquoted) - Booleans:
true/false,yes/no,on/off - Integers with size suffixes:
1k,2mb,1gb - Floats, ISO8601 datetimes (
2006-01-02T15:04:05Z) - Block strings:
(multi-line raw text) - Hex escapes:
\x##, plus\t,\n,\r,\",\\
Component 2: Parser (NatsConfParser.cs)
Direct port of Go conf/parse.go (~529 lines Go → ~300 lines C#).
Consumes token stream, produces Dictionary<string, object?>:
- Stack-based context tracking for nested maps/arrays
- Variable resolution:
$VARsearches current context stack, then environment - Cycle detection for variable references
include "path"resolves relative to current config file- Pedantic mode with line/column tracking for error messages
- SHA256 digest of parsed content for reload change detection
Component 3: Config Processor (ConfigProcessor.cs)
Maps parsed dictionary keys to NatsOptions fields. Port of Go processConfigFileLine in opts.go.
Key categories handled:
- Network:
listen,port,host/net,client_advertise,max_connections/max_conn - Logging:
debug,trace,trace_verbose,logtime,logtime_utc,logfile/log_file,log_size_limit,log_max_num,syslog,remote_syslog - Auth:
authorization { ... }block (username, password, token, users, nkeys, timeout),no_auth_user - Accounts:
accounts { ... }block,system_account,no_system_account - TLS:
tls { ... }block (cert_file, key_file, ca_file, verify, verify_and_map, timeout, pinned_certs, handshake_first, handshake_first_fallback),allow_non_tls - Monitoring:
http_port/monitor_port,https_port,http/https(combined),http_base_path - Limits:
max_payload,max_control_line,max_pending,max_subs,max_sub_tokens,max_traced_msg_len,write_deadline - Ping:
ping_interval,ping_max/ping_max_out - Lifecycle:
lame_duck_duration,lame_duck_grace_period - Files:
pidfile/pid_file,ports_file_dir - Misc:
server_name,server_tags,disable_sublist_cache,max_closed_clients,prof_port
Error handling: accumulate all errors, report together (not fail-fast). Unknown keys silently ignored (allows cluster/JetStream configs to coexist).
Component 4: Hot Reload (ConfigReloader.cs)
Reloadable Options (matching Go)
- Logging: Debug, Trace, TraceVerbose, Logtime, LogtimeUTC, LogFile, LogSizeLimit, LogMaxFiles, Syslog, RemoteSyslog
- Auth: Username, Password, Authorization, Users, NKeys, NoAuthUser, AuthTimeout
- Limits: MaxConnections, MaxPayload, MaxPending, WriteDeadline, PingInterval, MaxPingsOut, MaxControlLine, MaxSubs, MaxSubTokens, MaxTracedMsgLen
- TLS: cert/key/CA file paths (reload certs without restart)
- Misc: Tags, LameDuckDuration, LameDuckGracePeriod, ClientAdvertise, MaxClosedClients
Non-Reloadable (error if changed)
- Host, Port, ServerName
IConfigChange Interface
interface IConfigChange
{
string Name { get; }
void Apply(NatsServer server);
bool IsLoggingChange { get; }
bool IsAuthChange { get; }
bool IsTlsChange { get; }
}
Reload Flow
- SIGHUP →
NatsServer.ReloadConfig() - Re-parse config file via
ConfigProcessor.ProcessConfigFile() - Merge with CLI flag snapshot (CLI always wins)
ConfigReloader.Diff(oldOpts, newOpts)→ list ofIConfigChange- Validate: reject if non-reloadable options changed
- Apply each change to running server (logging, auth, limits, TLS grouped)
- Log applied changes at Information level, errors at Warning
New NatsOptions Fields
Added for single-server parity with Go:
| Field | Type | Default | Go equivalent |
|---|---|---|---|
ClientAdvertise |
string? | null | client_advertise |
TraceVerbose |
bool | false | trace_verbose |
MaxTracedMsgLen |
int | 0 | max_traced_msg_len |
DisableSublistCache |
bool | false | disable_sublist_cache |
ConnectErrorReports |
int | 3600 | connect_error_reports |
ReconnectErrorReports |
int | 1 | reconnect_error_reports |
NoHeaderSupport |
bool | false | no_header_support |
MaxClosedClients |
int | 10000 | max_closed_clients |
NoSystemAccount |
bool | false | no_system_account |
SystemAccount |
string? | null | system_account |
Integration Points
NatsServer.cs
- Constructor: if
ConfigFileset, parse before startup - SIGHUP handler: call
ReloadConfig()instead of warning log - New
ReloadConfig()method for reload orchestration - Store CLI flag snapshot (
HashSet<string> InCmdLine)
Program.cs
- Parse config file after defaults, before CLI args
- Track CLI-set options in
InCmdLine - Rebuild Serilog config on logging reload
File Layout
src/NATS.Server/Configuration/
NatsConfLexer.cs (~400 lines)
NatsConfParser.cs (~300 lines)
NatsConfToken.cs (~30 lines)
ConfigProcessor.cs (~350 lines)
ConfigReloader.cs (~250 lines)
IConfigChange.cs (~15 lines)
Test Plan
Test Files
NatsConfLexerTests.cs— all token types, comments, escapes, edge casesNatsConfParserTests.cs— nested blocks, arrays, variables, includes, errorsConfigProcessorTests.cs— all option key mappings, type coercion, error collectionConfigReloadTests.cs— reload flow, reloadable vs non-reloadable, CLI precedence
Test Data
tests/NATS.Server.Tests/TestData/
basic.conf — minimal server config
auth.conf — authorization block with users/nkeys
tls.conf — TLS configuration
full.conf — all supported options
includes/ — include directive tests
invalid.conf — error case configs
Task Reference
Implementation tasks will be created via the writing-plans skill.