// Copyright 2017-2026 The NATS Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Adapted from server/reload.go in the NATS server Go source. namespace ZB.MOM.NatsNet.Server; // ============================================================================= // IReloadOption — mirrors Go `option` interface in reload.go // ============================================================================= /// /// Represents a hot-swappable configuration setting that can be applied to a /// running server. Mirrors Go option interface in server/reload.go. /// public interface IReloadOption { /// Apply this option to the running server. void Apply(NatsServer server); /// Returns true if this option requires reloading the logger. bool IsLoggingChange(); /// /// Returns true if this option requires reloading the cached trace level. /// Clients store trace level separately. /// bool IsTraceLevelChange(); /// Returns true if this option requires reloading authorization. bool IsAuthChange(); /// Returns true if this option requires reloading TLS. bool IsTlsChange(); /// Returns true if this option requires reloading cluster permissions. bool IsClusterPermsChange(); /// /// Returns true if this option requires special handling for changes in /// cluster pool size or accounts list. /// bool IsClusterPoolSizeOrAccountsChange(); /// /// Returns true if this option indicates a change in the server's JetStream config. /// Account changes are handled separately in reloadAuthorization. /// bool IsJetStreamChange(); /// Returns true if this change requires publishing the server's statz. bool IsStatszChange(); } // ============================================================================= // NoopReloadOption — mirrors Go `noopOption` struct in reload.go // ============================================================================= /// /// Base class providing no-op implementations for all /// methods. Concrete option types override only the methods relevant to them. /// Mirrors Go noopOption struct in server/reload.go. /// public abstract class NoopReloadOption : IReloadOption { /// public virtual void Apply(NatsServer server) { } /// public virtual bool IsLoggingChange() => false; /// public virtual bool IsTraceLevelChange() => false; /// public virtual bool IsAuthChange() => false; /// public virtual bool IsTlsChange() => false; /// public virtual bool IsClusterPermsChange() => false; /// public virtual bool IsClusterPoolSizeOrAccountsChange() => false; /// public virtual bool IsJetStreamChange() => false; /// public virtual bool IsStatszChange() => false; } // ============================================================================= // Intermediate base classes (mirrors Go loggingOption / traceLevelOption) // ============================================================================= /// /// Base for all logging-related reload options. /// Mirrors Go loggingOption struct. /// internal abstract class LoggingReloadOption : NoopReloadOption { public override bool IsLoggingChange() => true; } /// /// Base for all trace-level reload options. /// Mirrors Go traceLevelOption struct. /// internal abstract class TraceLevelReloadOption : LoggingReloadOption { public override bool IsTraceLevelChange() => true; } /// /// Base for all authorization-related reload options. /// Mirrors Go authOption struct. /// internal abstract class AuthReloadOption : NoopReloadOption { public override bool IsAuthChange() => true; } /// /// Base for TLS reload options. /// Mirrors Go tlsOption (as a base, not the concrete type). /// internal abstract class TlsBaseReloadOption : NoopReloadOption { public override bool IsTlsChange() => true; } // ============================================================================= // Logging & Trace option types // ============================================================================= /// /// Reload option for the trace setting. /// Mirrors Go traceOption struct in reload.go. /// internal sealed class TraceReloadOption : TraceLevelReloadOption { private readonly bool _newValue; public TraceReloadOption(bool newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: trace = {0}", _newValue); } /// /// Reload option for the trace_verbose setting. /// Mirrors Go traceVerboseOption struct in reload.go. /// internal sealed class TraceVerboseReloadOption : TraceLevelReloadOption { private readonly bool _newValue; public TraceVerboseReloadOption(bool newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: trace_verbose = {0}", _newValue); } /// /// Reload option for the trace_headers setting. /// Mirrors Go traceHeadersOption struct in reload.go. /// internal sealed class TraceHeadersReloadOption : TraceLevelReloadOption { private readonly bool _newValue; public TraceHeadersReloadOption(bool newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: trace_headers = {0}", _newValue); } /// /// Reload option for the debug setting. /// Mirrors Go debugOption struct in reload.go. /// internal sealed class DebugReloadOption : LoggingReloadOption { private readonly bool _newValue; public DebugReloadOption(bool newValue) => _newValue = newValue; public override void Apply(NatsServer server) { server.Noticef("Reloaded: debug = {0}", _newValue); // TODO: session 13 — call server.ReloadDebugRaftNodes(_newValue) } } /// /// Reload option for the logtime setting. /// Mirrors Go logtimeOption struct in reload.go. /// internal sealed class LogtimeReloadOption : LoggingReloadOption { private readonly bool _newValue; public LogtimeReloadOption(bool newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: logtime = {0}", _newValue); } /// /// Reload option for the logtime_utc setting. /// Mirrors Go logtimeUTCOption struct in reload.go. /// internal sealed class LogtimeUtcReloadOption : LoggingReloadOption { private readonly bool _newValue; public LogtimeUtcReloadOption(bool newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: logtime_utc = {0}", _newValue); } /// /// Reload option for the log_file setting. /// Mirrors Go logfileOption struct in reload.go. /// internal sealed class LogFileReloadOption : LoggingReloadOption { private readonly string _newValue; public LogFileReloadOption(string newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: log_file = {0}", _newValue); } /// /// Reload option for the syslog setting. /// Mirrors Go syslogOption struct in reload.go. /// internal sealed class SyslogReloadOption : LoggingReloadOption { private readonly bool _newValue; public SyslogReloadOption(bool newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: syslog = {0}", _newValue); } /// /// Reload option for the remote_syslog setting. /// Mirrors Go remoteSyslogOption struct in reload.go. /// internal sealed class RemoteSyslogReloadOption : LoggingReloadOption { private readonly string _newValue; public RemoteSyslogReloadOption(string newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: remote_syslog = {0}", _newValue); } // ============================================================================= // TLS option types // ============================================================================= /// /// Reload option for the tls setting. /// Mirrors Go tlsOption struct in reload.go. /// The TLS config is stored as object? because the full /// TlsConfig type is not yet ported. /// TODO: session 13 — replace object? with the ported TlsConfig type. /// internal sealed class TlsReloadOption : NoopReloadOption { // TODO: session 13 — replace object? with ported TlsConfig type private readonly object? _newValue; public TlsReloadOption(object? newValue) => _newValue = newValue; public override bool IsTlsChange() => true; public override void Apply(NatsServer server) { var message = _newValue is null ? "disabled" : "enabled"; server.Noticef("Reloaded: tls = {0}", message); // TODO: session 13 — update server.Info.TLSRequired / TLSVerify } } /// /// Reload option for the TLS timeout setting. /// Mirrors Go tlsTimeoutOption struct in reload.go. /// internal sealed class TlsTimeoutReloadOption : NoopReloadOption { private readonly double _newValue; public TlsTimeoutReloadOption(double newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: tls timeout = {0}", _newValue); } /// /// Reload option for the TLS pinned_certs setting. /// Mirrors Go tlsPinnedCertOption struct in reload.go. /// The pinned cert set is stored as object? pending the port /// of the PinnedCertSet type. /// TODO: session 13 — replace object? with ported PinnedCertSet type. /// internal sealed class TlsPinnedCertReloadOption : NoopReloadOption { // TODO: session 13 — replace object? with ported PinnedCertSet type private readonly object? _newValue; public TlsPinnedCertReloadOption(object? newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: pinned_certs"); } /// /// Reload option for the TLS handshake_first setting. /// Mirrors Go tlsHandshakeFirst struct in reload.go. /// internal sealed class TlsHandshakeFirstReloadOption : NoopReloadOption { private readonly bool _newValue; public TlsHandshakeFirstReloadOption(bool newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: Client TLS handshake first: {0}", _newValue); } /// /// Reload option for the TLS handshake_first_fallback delay setting. /// Mirrors Go tlsHandshakeFirstFallback struct in reload.go. /// internal sealed class TlsHandshakeFirstFallbackReloadOption : NoopReloadOption { private readonly TimeSpan _newValue; public TlsHandshakeFirstFallbackReloadOption(TimeSpan newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: Client TLS handshake first fallback delay: {0}", _newValue); } // ============================================================================= // Authorization option types // ============================================================================= /// /// Reload option for the username authorization setting. /// Mirrors Go usernameOption struct in reload.go. /// internal sealed class UsernameReloadOption : AuthReloadOption { public override void Apply(NatsServer server) => server.Noticef("Reloaded: authorization username"); } /// /// Reload option for the password authorization setting. /// Mirrors Go passwordOption struct in reload.go. /// internal sealed class PasswordReloadOption : AuthReloadOption { public override void Apply(NatsServer server) => server.Noticef("Reloaded: authorization password"); } /// /// Reload option for the token authorization setting. /// Mirrors Go authorizationOption struct in reload.go. /// internal sealed class AuthorizationReloadOption : AuthReloadOption { public override void Apply(NatsServer server) => server.Noticef("Reloaded: authorization token"); } /// /// Reload option for the authorization timeout setting. /// Note: this is a NoopReloadOption (not auth) because authorization /// will be reloaded with options separately. /// Mirrors Go authTimeoutOption struct in reload.go. /// internal sealed class AuthTimeoutReloadOption : NoopReloadOption { private readonly double _newValue; public AuthTimeoutReloadOption(double newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: authorization timeout = {0}", _newValue); } /// /// Reload option for the tags setting. /// Mirrors Go tagsOption struct in reload.go. /// internal sealed class TagsReloadOption : NoopReloadOption { public override void Apply(NatsServer server) => server.Noticef("Reloaded: tags"); public override bool IsStatszChange() => true; } /// /// Reload option for the metadata setting. /// Mirrors Go metadataOption struct in reload.go. /// internal sealed class MetadataReloadOption : NoopReloadOption { public override void Apply(NatsServer server) => server.Noticef("Reloaded: metadata"); public override bool IsStatszChange() => true; } /// /// Reload option for the authorization users setting. /// Mirrors Go usersOption struct in reload.go. /// internal sealed class UsersReloadOption : AuthReloadOption { public override void Apply(NatsServer server) => server.Noticef("Reloaded: authorization users"); } /// /// Reload option for the authorization nkeys setting. /// Mirrors Go nkeysOption struct in reload.go. /// internal sealed class NkeysReloadOption : AuthReloadOption { public override void Apply(NatsServer server) => server.Noticef("Reloaded: authorization nkey users"); } /// /// Reload option for the accounts setting. /// Mirrors Go accountsOption struct in reload.go. /// internal sealed class AccountsReloadOption : AuthReloadOption { public override void Apply(NatsServer server) => server.Noticef("Reloaded: accounts"); } // ============================================================================= // Cluster option types // ============================================================================= /// /// Reload option for the cluster setting. /// Stores cluster options as object? pending the port of ClusterOpts. /// Mirrors Go clusterOption struct in reload.go. /// TODO: session 13 — replace object? with ported ClusterOpts type. /// internal sealed class ClusterReloadOption : AuthReloadOption { // TODO: session 13 — replace object? with ported ClusterOpts type private readonly object? _newValue; private readonly bool _permsChanged; private readonly bool _poolSizeChanged; private readonly bool _compressChanged; private readonly string[] _accsAdded; private readonly string[] _accsRemoved; public ClusterReloadOption( object? newValue, bool permsChanged, bool poolSizeChanged, bool compressChanged, string[] accsAdded, string[] accsRemoved) { _newValue = newValue; _permsChanged = permsChanged; _poolSizeChanged = poolSizeChanged; _compressChanged = compressChanged; _accsAdded = accsAdded; _accsRemoved = accsRemoved; } public override bool IsClusterPermsChange() => _permsChanged; public override bool IsClusterPoolSizeOrAccountsChange() => _poolSizeChanged || _accsAdded.Length > 0 || _accsRemoved.Length > 0; public override void Apply(NatsServer server) { // TODO: session 13 — full cluster apply logic (TLS, route info, compression) server.Noticef("Reloaded: cluster"); } } /// /// Reload option for the cluster routes setting. /// Routes to add/remove are stored as object[] pending the port of URL handling. /// Mirrors Go routesOption struct in reload.go. /// TODO: session 13 — replace object[] with Uri[] when route types are ported. /// internal sealed class RoutesReloadOption : NoopReloadOption { // TODO: session 13 — replace object[] with Uri[] when route URL types are ported private readonly object[] _add; private readonly object[] _remove; public RoutesReloadOption(object[] add, object[] remove) { _add = add; _remove = remove; } public override void Apply(NatsServer server) { // TODO: session 13 — add/remove routes, update varzUpdateRouteURLs server.Noticef("Reloaded: cluster routes"); } } // ============================================================================= // Connection limit & network option types // ============================================================================= /// /// Reload option for the max_connections setting. /// Mirrors Go maxConnOption struct in reload.go. /// internal sealed class MaxConnReloadOption : NoopReloadOption { private readonly int _newValue; public MaxConnReloadOption(int newValue) => _newValue = newValue; public override void Apply(NatsServer server) { // TODO: session 13 — close random connections if over limit server.Noticef("Reloaded: max_connections = {0}", _newValue); } } /// /// Reload option for the pid_file setting. /// Mirrors Go pidFileOption struct in reload.go. /// internal sealed class PidFileReloadOption : NoopReloadOption { private readonly string _newValue; public PidFileReloadOption(string newValue) => _newValue = newValue; public override void Apply(NatsServer server) { if (string.IsNullOrEmpty(_newValue)) return; // TODO: session 13 — call server.LogPid() server.Noticef("Reloaded: pid_file = {0}", _newValue); } } /// /// Reload option for the ports_file_dir setting. /// Mirrors Go portsFileDirOption struct in reload.go. /// internal sealed class PortsFileDirReloadOption : NoopReloadOption { private readonly string _oldValue; private readonly string _newValue; public PortsFileDirReloadOption(string oldValue, string newValue) { _oldValue = oldValue; _newValue = newValue; } public override void Apply(NatsServer server) { // TODO: session 13 — call server.DeletePortsFile(_oldValue) and server.LogPorts() server.Noticef("Reloaded: ports_file_dir = {0}", _newValue); } } /// /// Reload option for the max_control_line setting. /// Mirrors Go maxControlLineOption struct in reload.go. /// internal sealed class MaxControlLineReloadOption : NoopReloadOption { private readonly int _newValue; public MaxControlLineReloadOption(int newValue) => _newValue = newValue; public override void Apply(NatsServer server) { // TODO: session 13 — update mcl on each connected client server.Noticef("Reloaded: max_control_line = {0}", _newValue); } } /// /// Reload option for the max_payload setting. /// Mirrors Go maxPayloadOption struct in reload.go. /// internal sealed class MaxPayloadReloadOption : NoopReloadOption { private readonly int _newValue; public MaxPayloadReloadOption(int newValue) => _newValue = newValue; public override void Apply(NatsServer server) { // TODO: session 13 — update server info and mpay on each client server.Noticef("Reloaded: max_payload = {0}", _newValue); } } /// /// Reload option for the ping_interval setting. /// Mirrors Go pingIntervalOption struct in reload.go. /// internal sealed class PingIntervalReloadOption : NoopReloadOption { private readonly TimeSpan _newValue; public PingIntervalReloadOption(TimeSpan newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: ping_interval = {0}", _newValue); } /// /// Reload option for the ping_max setting. /// Mirrors Go maxPingsOutOption struct in reload.go. /// internal sealed class MaxPingsOutReloadOption : NoopReloadOption { private readonly int _newValue; public MaxPingsOutReloadOption(int newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: ping_max = {0}", _newValue); } /// /// Reload option for the write_deadline setting. /// Mirrors Go writeDeadlineOption struct in reload.go. /// internal sealed class WriteDeadlineReloadOption : NoopReloadOption { private readonly TimeSpan _newValue; public WriteDeadlineReloadOption(TimeSpan newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: write_deadline = {0}", _newValue); } /// /// Reload option for the client_advertise setting. /// Mirrors Go clientAdvertiseOption struct in reload.go. /// internal sealed class ClientAdvertiseReloadOption : NoopReloadOption { private readonly string _newValue; public ClientAdvertiseReloadOption(string newValue) => _newValue = newValue; public override void Apply(NatsServer server) { // TODO: session 13 — call server.SetInfoHostPort() server.Noticef("Reload: client_advertise = {0}", _newValue); } } // ============================================================================= // JetStream option type // ============================================================================= /// /// Reload option for the jetstream setting. /// Mirrors Go jetStreamOption struct in reload.go. /// internal sealed class JetStreamReloadOption : NoopReloadOption { private readonly bool _newValue; public JetStreamReloadOption(bool newValue) => _newValue = newValue; public override bool IsJetStreamChange() => true; public override bool IsStatszChange() => true; public override void Apply(NatsServer server) => server.Noticef("Reloaded: JetStream"); } // ============================================================================= // Miscellaneous option types // ============================================================================= /// /// Reload option for the default_sentinel setting. /// Mirrors Go defaultSentinelOption struct in reload.go. /// internal sealed class DefaultSentinelReloadOption : NoopReloadOption { private readonly string _newValue; public DefaultSentinelReloadOption(string newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: default_sentinel = {0}", _newValue); } /// /// Reload option for the OCSP setting. /// The new value is stored as object? pending the port of OCSPConfig. /// Mirrors Go ocspOption struct in reload.go. /// TODO: session 13 — replace object? with ported OcspConfig type. /// internal sealed class OcspReloadOption : TlsBaseReloadOption { // TODO: session 13 — replace object? with ported OcspConfig type private readonly object? _newValue; public OcspReloadOption(object? newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: OCSP"); } /// /// Reload option for the OCSP response cache setting. /// The new value is stored as object? pending the port of /// OCSPResponseCacheConfig. /// Mirrors Go ocspResponseCacheOption struct in reload.go. /// TODO: session 13 — replace object? with ported OcspResponseCacheConfig type. /// internal sealed class OcspResponseCacheReloadOption : TlsBaseReloadOption { // TODO: session 13 — replace object? with ported OcspResponseCacheConfig type private readonly object? _newValue; public OcspResponseCacheReloadOption(object? newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded OCSP peer cache"); } /// /// Reload option for the connect_error_reports setting. /// Mirrors Go connectErrorReports struct in reload.go. /// internal sealed class ConnectErrorReportsReloadOption : NoopReloadOption { private readonly int _newValue; public ConnectErrorReportsReloadOption(int newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: connect_error_reports = {0}", _newValue); } /// /// Reload option for the reconnect_error_reports setting. /// Mirrors Go reconnectErrorReports struct in reload.go. /// internal sealed class ReconnectErrorReportsReloadOption : NoopReloadOption { private readonly int _newValue; public ReconnectErrorReportsReloadOption(int newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: reconnect_error_reports = {0}", _newValue); } /// /// Reload option for the max_traced_msg_len setting. /// Mirrors Go maxTracedMsgLenOption struct in reload.go. /// internal sealed class MaxTracedMsgLenReloadOption : NoopReloadOption { private readonly int _newValue; public MaxTracedMsgLenReloadOption(int newValue) => _newValue = newValue; public override void Apply(NatsServer server) { // TODO: session 13 — update server.Opts.MaxTracedMsgLen under lock server.Noticef("Reloaded: max_traced_msg_len = {0}", _newValue); } } // ============================================================================= // MQTT option types // ============================================================================= /// /// Reload option for the MQTT ack_wait setting. /// Mirrors Go mqttAckWaitReload struct in reload.go. /// internal sealed class MqttAckWaitReloadOption : NoopReloadOption { private readonly TimeSpan _newValue; public MqttAckWaitReloadOption(TimeSpan newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: MQTT ack_wait = {0}", _newValue); } /// /// Reload option for the MQTT max_ack_pending setting. /// Mirrors Go mqttMaxAckPendingReload struct in reload.go. /// internal sealed class MqttMaxAckPendingReloadOption : NoopReloadOption { private readonly ushort _newValue; public MqttMaxAckPendingReloadOption(ushort newValue) => _newValue = newValue; public override void Apply(NatsServer server) { // TODO: session 13 — call server.MqttUpdateMaxAckPending(_newValue) server.Noticef("Reloaded: MQTT max_ack_pending = {0}", _newValue); } } /// /// Reload option for the MQTT stream_replicas setting. /// Mirrors Go mqttStreamReplicasReload struct in reload.go. /// internal sealed class MqttStreamReplicasReloadOption : NoopReloadOption { private readonly int _newValue; public MqttStreamReplicasReloadOption(int newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: MQTT stream_replicas = {0}", _newValue); } /// /// Reload option for the MQTT consumer_replicas setting. /// Mirrors Go mqttConsumerReplicasReload struct in reload.go. /// internal sealed class MqttConsumerReplicasReloadOption : NoopReloadOption { private readonly int _newValue; public MqttConsumerReplicasReloadOption(int newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: MQTT consumer_replicas = {0}", _newValue); } /// /// Reload option for the MQTT consumer_memory_storage setting. /// Mirrors Go mqttConsumerMemoryStorageReload struct in reload.go. /// internal sealed class MqttConsumerMemoryStorageReloadOption : NoopReloadOption { private readonly bool _newValue; public MqttConsumerMemoryStorageReloadOption(bool newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: MQTT consumer_memory_storage = {0}", _newValue); } /// /// Reload option for the MQTT consumer_inactive_threshold setting. /// Mirrors Go mqttInactiveThresholdReload struct in reload.go. /// internal sealed class MqttInactiveThresholdReloadOption : NoopReloadOption { private readonly TimeSpan _newValue; public MqttInactiveThresholdReloadOption(TimeSpan newValue) => _newValue = newValue; public override void Apply(NatsServer server) => server.Noticef("Reloaded: MQTT consumer_inactive_threshold = {0}", _newValue); } // ============================================================================= // Profiling option type // ============================================================================= /// /// Reload option for the prof_block_rate setting. /// Mirrors Go profBlockRateReload struct in reload.go. /// internal sealed class ProfBlockRateReloadOption : NoopReloadOption { private readonly int _newValue; public ProfBlockRateReloadOption(int newValue) => _newValue = newValue; public override void Apply(NatsServer server) { // TODO: session 13 — call server.SetBlockProfileRate(_newValue) server.Noticef("Reloaded: prof_block_rate = {0}", _newValue); } } // ============================================================================= // LeafNode option type // ============================================================================= /// /// Reload option for leaf-node settings (TLS handshake-first, compression, disabled). /// Mirrors Go leafNodeOption struct in reload.go. /// internal sealed class LeafNodeReloadOption : NoopReloadOption { private readonly bool _tlsFirstChanged; private readonly bool _compressionChanged; private readonly bool _disabledChanged; public LeafNodeReloadOption(bool tlsFirstChanged, bool compressionChanged, bool disabledChanged) { _tlsFirstChanged = tlsFirstChanged; _compressionChanged = compressionChanged; _disabledChanged = disabledChanged; } public override void Apply(NatsServer server) { // TODO: session 13 — full leaf-node apply logic from Go leafNodeOption.Apply() if (_tlsFirstChanged) server.Noticef("Reloaded: LeafNode TLS HandshakeFirst settings"); if (_compressionChanged) server.Noticef("Reloaded: LeafNode compression settings"); if (_disabledChanged) server.Noticef("Reloaded: LeafNode disabled/enabled state"); } } // ============================================================================= // NoFastProducerStall option type // ============================================================================= /// /// Reload option for the no_fast_producer_stall setting. /// Mirrors Go noFastProdStallReload struct in reload.go. /// internal sealed class NoFastProducerStallReloadOption : NoopReloadOption { private readonly bool _noStall; public NoFastProducerStallReloadOption(bool noStall) => _noStall = noStall; public override void Apply(NatsServer server) { var not = _noStall ? "not " : string.Empty; server.Noticef("Reloaded: fast producers will {0}be stalled", not); } } // ============================================================================= // Proxies option type // ============================================================================= /// /// Reload option for the proxies trusted keys setting. /// Mirrors Go proxiesReload struct in reload.go. /// internal sealed class ProxiesReloadOption : NoopReloadOption { private readonly string[] _add; private readonly string[] _del; public ProxiesReloadOption(string[] add, string[] del) { _add = add; _del = del; } public override void Apply(NatsServer server) { // TODO: session 13 — disconnect proxied clients for removed keys, // call server.ProcessProxiesTrustedKeys() if (_del.Length > 0) server.Noticef("Reloaded: proxies trusted keys {0} were removed", string.Join(", ", _del)); if (_add.Length > 0) server.Noticef("Reloaded: proxies trusted keys {0} were added", string.Join(", ", _add)); } } // ============================================================================= // ConfigReloader — stub for server/reload.go Reload() / ReloadOptions() // ============================================================================= /// /// Stub for the configuration reloader. /// Full reload logic (diffOptions, applyOptions, recheckPinnedCerts) will be /// implemented in a future session. /// Mirrors Go Server.Reload() and Server.ReloadOptions() in /// server/reload.go. /// internal sealed class ConfigReloader { // TODO: session 13 — full reload logic // Mirrors Go server.Reload() / server.ReloadOptions() in server/reload.go /// /// Stub: read and apply the server config file. /// Returns null on success; a non-null Exception describes the failure. /// public Exception? Reload(NatsServer server) => null; }