feat: port sessions 12 & 13 — Events/Monitoring/MsgTrace + Config Reload

Session 12 (218 features, IDs 854-950, 2166-2251, 2405-2439):
- EventTypes: system subjects, event message types, InternalState, ConnectEventMsg,
  DisconnectEventMsg, AccountNumConns, ServerIdentity, DataStats
- MonitorTypes: Connz, ConnInfo, ConnzOptions, ConnState, ProxyInfo, TlsPeerCert
- MonitorSortOptions: SortOpt, ConnInfos, all 13 sort comparers
- MsgTraceTypes: IMsgTrace, MsgTraceBase + 6 concrete types, custom JSON converter

Session 13 (89 features, IDs 2800-2888):
- ReloadOptions: IReloadOption interface, NoopReloadOption base, 50 option classes
  covering logging, TLS, auth, cluster, JetStream, MQTT, OCSP, misc
This commit is contained in:
Joseph Doherty
2026-02-26 15:46:14 -05:00
parent 12a14ec476
commit ce45dff994
11 changed files with 2971 additions and 47 deletions

View File

@@ -0,0 +1,996 @@
// 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
// =============================================================================
/// <summary>
/// Represents a hot-swappable configuration setting that can be applied to a
/// running server. Mirrors Go <c>option</c> interface in server/reload.go.
/// </summary>
public interface IReloadOption
{
/// <summary>Apply this option to the running server.</summary>
void Apply(NatsServer server);
/// <summary>Returns true if this option requires reloading the logger.</summary>
bool IsLoggingChange();
/// <summary>
/// Returns true if this option requires reloading the cached trace level.
/// Clients store trace level separately.
/// </summary>
bool IsTraceLevelChange();
/// <summary>Returns true if this option requires reloading authorization.</summary>
bool IsAuthChange();
/// <summary>Returns true if this option requires reloading TLS.</summary>
bool IsTlsChange();
/// <summary>Returns true if this option requires reloading cluster permissions.</summary>
bool IsClusterPermsChange();
/// <summary>
/// Returns true if this option requires special handling for changes in
/// cluster pool size or accounts list.
/// </summary>
bool IsClusterPoolSizeOrAccountsChange();
/// <summary>
/// Returns true if this option indicates a change in the server's JetStream config.
/// Account changes are handled separately in reloadAuthorization.
/// </summary>
bool IsJetStreamChange();
/// <summary>Returns true if this change requires publishing the server's statz.</summary>
bool IsStatszChange();
}
// =============================================================================
// NoopReloadOption — mirrors Go `noopOption` struct in reload.go
// =============================================================================
/// <summary>
/// Base class providing no-op implementations for all <see cref="IReloadOption"/>
/// methods. Concrete option types override only the methods relevant to them.
/// Mirrors Go <c>noopOption</c> struct in server/reload.go.
/// </summary>
public abstract class NoopReloadOption : IReloadOption
{
/// <inheritdoc/>
public virtual void Apply(NatsServer server) { }
/// <inheritdoc/>
public virtual bool IsLoggingChange() => false;
/// <inheritdoc/>
public virtual bool IsTraceLevelChange() => false;
/// <inheritdoc/>
public virtual bool IsAuthChange() => false;
/// <inheritdoc/>
public virtual bool IsTlsChange() => false;
/// <inheritdoc/>
public virtual bool IsClusterPermsChange() => false;
/// <inheritdoc/>
public virtual bool IsClusterPoolSizeOrAccountsChange() => false;
/// <inheritdoc/>
public virtual bool IsJetStreamChange() => false;
/// <inheritdoc/>
public virtual bool IsStatszChange() => false;
}
// =============================================================================
// Intermediate base classes (mirrors Go loggingOption / traceLevelOption)
// =============================================================================
/// <summary>
/// Base for all logging-related reload options.
/// Mirrors Go <c>loggingOption</c> struct.
/// </summary>
internal abstract class LoggingReloadOption : NoopReloadOption
{
public override bool IsLoggingChange() => true;
}
/// <summary>
/// Base for all trace-level reload options.
/// Mirrors Go <c>traceLevelOption</c> struct.
/// </summary>
internal abstract class TraceLevelReloadOption : LoggingReloadOption
{
public override bool IsTraceLevelChange() => true;
}
/// <summary>
/// Base for all authorization-related reload options.
/// Mirrors Go <c>authOption</c> struct.
/// </summary>
internal abstract class AuthReloadOption : NoopReloadOption
{
public override bool IsAuthChange() => true;
}
/// <summary>
/// Base for TLS reload options.
/// Mirrors Go <c>tlsOption</c> (as a base, not the concrete type).
/// </summary>
internal abstract class TlsBaseReloadOption : NoopReloadOption
{
public override bool IsTlsChange() => true;
}
// =============================================================================
// Logging & Trace option types
// =============================================================================
/// <summary>
/// Reload option for the <c>trace</c> setting.
/// Mirrors Go <c>traceOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>trace_verbose</c> setting.
/// Mirrors Go <c>traceVerboseOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>trace_headers</c> setting.
/// Mirrors Go <c>traceHeadersOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>debug</c> setting.
/// Mirrors Go <c>debugOption</c> struct in reload.go.
/// </summary>
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)
}
}
/// <summary>
/// Reload option for the <c>logtime</c> setting.
/// Mirrors Go <c>logtimeOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>logtime_utc</c> setting.
/// Mirrors Go <c>logtimeUTCOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>log_file</c> setting.
/// Mirrors Go <c>logfileOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>syslog</c> setting.
/// Mirrors Go <c>syslogOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>remote_syslog</c> setting.
/// Mirrors Go <c>remoteSyslogOption</c> struct in reload.go.
/// </summary>
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
// =============================================================================
/// <summary>
/// Reload option for the <c>tls</c> setting.
/// Mirrors Go <c>tlsOption</c> struct in reload.go.
/// The TLS config is stored as <c>object?</c> because the full
/// <c>TlsConfig</c> type is not yet ported.
/// TODO: session 13 — replace object? with the ported TlsConfig type.
/// </summary>
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
}
}
/// <summary>
/// Reload option for the TLS <c>timeout</c> setting.
/// Mirrors Go <c>tlsTimeoutOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the TLS <c>pinned_certs</c> setting.
/// Mirrors Go <c>tlsPinnedCertOption</c> struct in reload.go.
/// The pinned cert set is stored as <c>object?</c> pending the port
/// of the PinnedCertSet type.
/// TODO: session 13 — replace object? with ported PinnedCertSet type.
/// </summary>
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");
}
/// <summary>
/// Reload option for the TLS <c>handshake_first</c> setting.
/// Mirrors Go <c>tlsHandshakeFirst</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the TLS <c>handshake_first_fallback</c> delay setting.
/// Mirrors Go <c>tlsHandshakeFirstFallback</c> struct in reload.go.
/// </summary>
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
// =============================================================================
/// <summary>
/// Reload option for the <c>username</c> authorization setting.
/// Mirrors Go <c>usernameOption</c> struct in reload.go.
/// </summary>
internal sealed class UsernameReloadOption : AuthReloadOption
{
public override void Apply(NatsServer server)
=> server.Noticef("Reloaded: authorization username");
}
/// <summary>
/// Reload option for the <c>password</c> authorization setting.
/// Mirrors Go <c>passwordOption</c> struct in reload.go.
/// </summary>
internal sealed class PasswordReloadOption : AuthReloadOption
{
public override void Apply(NatsServer server)
=> server.Noticef("Reloaded: authorization password");
}
/// <summary>
/// Reload option for the <c>token</c> authorization setting.
/// Mirrors Go <c>authorizationOption</c> struct in reload.go.
/// </summary>
internal sealed class AuthorizationReloadOption : AuthReloadOption
{
public override void Apply(NatsServer server)
=> server.Noticef("Reloaded: authorization token");
}
/// <summary>
/// Reload option for the authorization <c>timeout</c> setting.
/// Note: this is a NoopReloadOption (not auth) because authorization
/// will be reloaded with options separately.
/// Mirrors Go <c>authTimeoutOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>tags</c> setting.
/// Mirrors Go <c>tagsOption</c> struct in reload.go.
/// </summary>
internal sealed class TagsReloadOption : NoopReloadOption
{
public override void Apply(NatsServer server)
=> server.Noticef("Reloaded: tags");
public override bool IsStatszChange() => true;
}
/// <summary>
/// Reload option for the <c>metadata</c> setting.
/// Mirrors Go <c>metadataOption</c> struct in reload.go.
/// </summary>
internal sealed class MetadataReloadOption : NoopReloadOption
{
public override void Apply(NatsServer server)
=> server.Noticef("Reloaded: metadata");
public override bool IsStatszChange() => true;
}
/// <summary>
/// Reload option for the authorization <c>users</c> setting.
/// Mirrors Go <c>usersOption</c> struct in reload.go.
/// </summary>
internal sealed class UsersReloadOption : AuthReloadOption
{
public override void Apply(NatsServer server)
=> server.Noticef("Reloaded: authorization users");
}
/// <summary>
/// Reload option for the authorization <c>nkeys</c> setting.
/// Mirrors Go <c>nkeysOption</c> struct in reload.go.
/// </summary>
internal sealed class NkeysReloadOption : AuthReloadOption
{
public override void Apply(NatsServer server)
=> server.Noticef("Reloaded: authorization nkey users");
}
/// <summary>
/// Reload option for the <c>accounts</c> setting.
/// Mirrors Go <c>accountsOption</c> struct in reload.go.
/// </summary>
internal sealed class AccountsReloadOption : AuthReloadOption
{
public override void Apply(NatsServer server)
=> server.Noticef("Reloaded: accounts");
}
// =============================================================================
// Cluster option types
// =============================================================================
/// <summary>
/// Reload option for the <c>cluster</c> setting.
/// Stores cluster options as <c>object?</c> pending the port of <c>ClusterOpts</c>.
/// Mirrors Go <c>clusterOption</c> struct in reload.go.
/// TODO: session 13 — replace object? with ported ClusterOpts type.
/// </summary>
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");
}
}
/// <summary>
/// Reload option for the cluster <c>routes</c> setting.
/// Routes to add/remove are stored as <c>object[]</c> pending the port of URL handling.
/// Mirrors Go <c>routesOption</c> struct in reload.go.
/// TODO: session 13 — replace object[] with Uri[] when route types are ported.
/// </summary>
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
// =============================================================================
/// <summary>
/// Reload option for the <c>max_connections</c> setting.
/// Mirrors Go <c>maxConnOption</c> struct in reload.go.
/// </summary>
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);
}
}
/// <summary>
/// Reload option for the <c>pid_file</c> setting.
/// Mirrors Go <c>pidFileOption</c> struct in reload.go.
/// </summary>
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);
}
}
/// <summary>
/// Reload option for the <c>ports_file_dir</c> setting.
/// Mirrors Go <c>portsFileDirOption</c> struct in reload.go.
/// </summary>
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);
}
}
/// <summary>
/// Reload option for the <c>max_control_line</c> setting.
/// Mirrors Go <c>maxControlLineOption</c> struct in reload.go.
/// </summary>
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);
}
}
/// <summary>
/// Reload option for the <c>max_payload</c> setting.
/// Mirrors Go <c>maxPayloadOption</c> struct in reload.go.
/// </summary>
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);
}
}
/// <summary>
/// Reload option for the <c>ping_interval</c> setting.
/// Mirrors Go <c>pingIntervalOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>ping_max</c> setting.
/// Mirrors Go <c>maxPingsOutOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>write_deadline</c> setting.
/// Mirrors Go <c>writeDeadlineOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>client_advertise</c> setting.
/// Mirrors Go <c>clientAdvertiseOption</c> struct in reload.go.
/// </summary>
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
// =============================================================================
/// <summary>
/// Reload option for the <c>jetstream</c> setting.
/// Mirrors Go <c>jetStreamOption</c> struct in reload.go.
/// </summary>
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
// =============================================================================
/// <summary>
/// Reload option for the <c>default_sentinel</c> setting.
/// Mirrors Go <c>defaultSentinelOption</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the OCSP setting.
/// The new value is stored as <c>object?</c> pending the port of <c>OCSPConfig</c>.
/// Mirrors Go <c>ocspOption</c> struct in reload.go.
/// TODO: session 13 — replace object? with ported OcspConfig type.
/// </summary>
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");
}
/// <summary>
/// Reload option for the OCSP response cache setting.
/// The new value is stored as <c>object?</c> pending the port of
/// <c>OCSPResponseCacheConfig</c>.
/// Mirrors Go <c>ocspResponseCacheOption</c> struct in reload.go.
/// TODO: session 13 — replace object? with ported OcspResponseCacheConfig type.
/// </summary>
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");
}
/// <summary>
/// Reload option for the <c>connect_error_reports</c> setting.
/// Mirrors Go <c>connectErrorReports</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>reconnect_error_reports</c> setting.
/// Mirrors Go <c>reconnectErrorReports</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the <c>max_traced_msg_len</c> setting.
/// Mirrors Go <c>maxTracedMsgLenOption</c> struct in reload.go.
/// </summary>
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
// =============================================================================
/// <summary>
/// Reload option for the MQTT <c>ack_wait</c> setting.
/// Mirrors Go <c>mqttAckWaitReload</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the MQTT <c>max_ack_pending</c> setting.
/// Mirrors Go <c>mqttMaxAckPendingReload</c> struct in reload.go.
/// </summary>
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);
}
}
/// <summary>
/// Reload option for the MQTT <c>stream_replicas</c> setting.
/// Mirrors Go <c>mqttStreamReplicasReload</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the MQTT <c>consumer_replicas</c> setting.
/// Mirrors Go <c>mqttConsumerReplicasReload</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the MQTT <c>consumer_memory_storage</c> setting.
/// Mirrors Go <c>mqttConsumerMemoryStorageReload</c> struct in reload.go.
/// </summary>
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);
}
/// <summary>
/// Reload option for the MQTT <c>consumer_inactive_threshold</c> setting.
/// Mirrors Go <c>mqttInactiveThresholdReload</c> struct in reload.go.
/// </summary>
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
// =============================================================================
/// <summary>
/// Reload option for the <c>prof_block_rate</c> setting.
/// Mirrors Go <c>profBlockRateReload</c> struct in reload.go.
/// </summary>
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
// =============================================================================
/// <summary>
/// Reload option for leaf-node settings (TLS handshake-first, compression, disabled).
/// Mirrors Go <c>leafNodeOption</c> struct in reload.go.
/// </summary>
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
// =============================================================================
/// <summary>
/// Reload option for the <c>no_fast_producer_stall</c> setting.
/// Mirrors Go <c>noFastProdStallReload</c> struct in reload.go.
/// </summary>
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
// =============================================================================
/// <summary>
/// Reload option for the <c>proxies</c> trusted keys setting.
/// Mirrors Go <c>proxiesReload</c> struct in reload.go.
/// </summary>
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()
// =============================================================================
/// <summary>
/// Stub for the configuration reloader.
/// Full reload logic (diffOptions, applyOptions, recheckPinnedCerts) will be
/// implemented in a future session.
/// Mirrors Go <c>Server.Reload()</c> and <c>Server.ReloadOptions()</c> in
/// server/reload.go.
/// </summary>
internal sealed class ConfigReloader
{
// TODO: session 13 — full reload logic
// Mirrors Go server.Reload() / server.ReloadOptions() in server/reload.go
/// <summary>
/// Stub: read and apply the server config file.
/// Returns null on success; a non-null Exception describes the failure.
/// </summary>
public Exception? Reload(NatsServer server) => null;
}