feat: add ClientClosedReason enum with 16 close reason values

This commit is contained in:
Joseph Doherty
2026-02-22 23:33:13 -05:00
parent 149c852510
commit 8bbfa54058
2 changed files with 75 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
namespace NATS.Server;
/// <summary>
/// Reason a client connection was closed.
/// Corresponds to Go server/client.go ClosedState (subset for single-server scope).
/// </summary>
public enum ClientClosedReason
{
None = 0,
ClientClosed,
AuthenticationTimeout,
AuthenticationViolation,
TlsHandshakeError,
SlowConsumerPendingBytes,
SlowConsumerWriteDeadline,
WriteError,
ReadError,
ParseError,
StaleConnection,
ProtocolViolation,
MaxPayloadExceeded,
MaxSubscriptionsExceeded,
ServerShutdown,
MsgHeaderViolation,
NoRespondersRequiresHeaders,
}
public static class ClientClosedReasonExtensions
{
public static string ToReasonString(this ClientClosedReason reason) => reason switch
{
ClientClosedReason.None => "",
ClientClosedReason.ClientClosed => "Client Closed",
ClientClosedReason.AuthenticationTimeout => "Authentication Timeout",
ClientClosedReason.AuthenticationViolation => "Authorization Violation",
ClientClosedReason.TlsHandshakeError => "TLS Handshake Error",
ClientClosedReason.SlowConsumerPendingBytes => "Slow Consumer (Pending Bytes)",
ClientClosedReason.SlowConsumerWriteDeadline => "Slow Consumer (Write Deadline)",
ClientClosedReason.WriteError => "Write Error",
ClientClosedReason.ReadError => "Read Error",
ClientClosedReason.ParseError => "Parse Error",
ClientClosedReason.StaleConnection => "Stale Connection",
ClientClosedReason.ProtocolViolation => "Protocol Violation",
ClientClosedReason.MaxPayloadExceeded => "Maximum Payload Exceeded",
ClientClosedReason.MaxSubscriptionsExceeded => "Maximum Subscriptions Exceeded",
ClientClosedReason.ServerShutdown => "Server Shutdown",
ClientClosedReason.MsgHeaderViolation => "Message Header Violation",
ClientClosedReason.NoRespondersRequiresHeaders => "No Responders Requires Headers",
_ => reason.ToString(),
};
}

View File

@@ -0,0 +1,24 @@
namespace NATS.Server.Tests;
public class ClientClosedReasonTests
{
[Fact]
public void All_expected_close_reasons_exist()
{
// Verify all 17 enum values exist and are distinct (None + 16 named reasons)
var values = Enum.GetValues<ClientClosedReason>();
values.Length.ShouldBe(17);
values.Distinct().Count().ShouldBe(17);
}
[Theory]
[InlineData(ClientClosedReason.ClientClosed, "Client Closed")]
[InlineData(ClientClosedReason.SlowConsumerPendingBytes, "Slow Consumer (Pending Bytes)")]
[InlineData(ClientClosedReason.SlowConsumerWriteDeadline, "Slow Consumer (Write Deadline)")]
[InlineData(ClientClosedReason.StaleConnection, "Stale Connection")]
[InlineData(ClientClosedReason.ServerShutdown, "Server Shutdown")]
public void ToReasonString_returns_human_readable_description(ClientClosedReason reason, string expected)
{
reason.ToReasonString().ShouldBe(expected);
}
}