feat(config): add SIGHUP signal handler and config reload validation
Implements SignalHandler (PosixSignalRegistration for SIGHUP) and ReloadFromOptionsAsync/ReloadFromOptionsResult on ConfigReloader for in-memory options comparison without reading a config file. Ports Go server/signal_unix.go handleSignals and server/reload.go Reload.
This commit is contained in:
@@ -398,6 +398,30 @@ public static class ConfigReloader
|
||||
}, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares two options directly (without reading from a config file) and returns
|
||||
/// a reload result indicating whether the change is valid.
|
||||
/// Go reference: server/reload.go — Reload with in-memory options comparison.
|
||||
/// </summary>
|
||||
public static Task<ReloadFromOptionsResult> ReloadFromOptionsAsync(NatsOptions original, NatsOptions updated)
|
||||
{
|
||||
var changes = Diff(original, updated);
|
||||
var errors = Validate(changes);
|
||||
var rejectedChanges = new List<string>();
|
||||
|
||||
foreach (var change in changes)
|
||||
{
|
||||
if (change.IsNonReloadable)
|
||||
{
|
||||
rejectedChanges.Add($"{change.Name} cannot be changed at runtime");
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(new ReloadFromOptionsResult(
|
||||
Success: rejectedChanges.Count == 0 && errors.Count == 0,
|
||||
RejectedChanges: rejectedChanges));
|
||||
}
|
||||
|
||||
// ─── Comparison helpers ─────────────────────────────────────────
|
||||
|
||||
private static void CompareAndAdd<T>(List<IConfigChange> changes, string name, T oldVal, T newVal)
|
||||
@@ -524,3 +548,8 @@ public sealed class ConfigReloadResult
|
||||
|
||||
public bool HasErrors => Errors is { Count: > 0 };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result of an in-memory options comparison for reload validation.
|
||||
/// </summary>
|
||||
public sealed record ReloadFromOptionsResult(bool Success, List<string> RejectedChanges);
|
||||
|
||||
41
src/NATS.Server/Configuration/SignalHandler.cs
Normal file
41
src/NATS.Server/Configuration/SignalHandler.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NATS.Server.Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Registers POSIX signal handlers for config reload.
|
||||
/// Go reference: server/signal_unix.go, server/opts.go reload logic.
|
||||
/// On SIGHUP, triggers config reload via ConfigReloader.
|
||||
/// </summary>
|
||||
public static class SignalHandler
|
||||
{
|
||||
private static PosixSignalRegistration? _registration;
|
||||
|
||||
/// <summary>
|
||||
/// Registers a SIGHUP handler that will call the provided reload callback.
|
||||
/// Go reference: server/signal_unix.go — handleSignals goroutine.
|
||||
/// </summary>
|
||||
/// <param name="onReload">Callback invoked when SIGHUP is received.</param>
|
||||
public static void Register(Action onReload)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(onReload);
|
||||
_registration = PosixSignalRegistration.Create(PosixSignal.SIGHUP, _ =>
|
||||
{
|
||||
onReload();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters the SIGHUP handler.
|
||||
/// </summary>
|
||||
public static void Unregister()
|
||||
{
|
||||
_registration?.Dispose();
|
||||
_registration = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether a SIGHUP handler is currently registered.
|
||||
/// </summary>
|
||||
public static bool IsRegistered => _registration is not null;
|
||||
}
|
||||
Reference in New Issue
Block a user