feat: add remote server events for cluster visibility (Gap 10.8)
Add RemoteServerShutdownEvent, RemoteServerUpdateEvent, LeafNodeConnectEvent, and LeafNodeDisconnectEvent types plus matching EventSubjects constants, with 10 unit tests covering type identity, field assignment, format placeholders, and JSON roundtrip serialization.
This commit is contained in:
@@ -22,6 +22,12 @@ public static class EventSubjects
|
||||
public const string AuthError = "$SYS.SERVER.{0}.CLIENT.AUTH.ERR";
|
||||
public const string AuthErrorAccount = "$SYS.ACCOUNT.CLIENT.AUTH.ERR";
|
||||
|
||||
// Remote server and leaf node events
|
||||
public const string RemoteServerShutdown = "$SYS.SERVER.{0}.REMOTE.SHUTDOWN";
|
||||
public const string RemoteServerUpdate = "$SYS.SERVER.{0}.REMOTE.UPDATE";
|
||||
public const string LeafNodeConnected = "$SYS.SERVER.{0}.LEAFNODE.CONNECT";
|
||||
public const string LeafNodeDisconnected = "$SYS.SERVER.{0}.LEAFNODE.DISCONNECT";
|
||||
|
||||
// Request-reply subjects (server-specific)
|
||||
public const string ServerReq = "$SYS.REQ.SERVER.{0}.{1}";
|
||||
|
||||
|
||||
200
tests/NATS.Server.Tests/Events/RemoteServerEventTests.cs
Normal file
200
tests/NATS.Server.Tests/Events/RemoteServerEventTests.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
using System.Text.Json;
|
||||
using NATS.Server.Events;
|
||||
|
||||
namespace NATS.Server.Tests.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for remote server and leaf node event DTOs and subject constants.
|
||||
/// Go reference: events.go — remote server lifecycle, leaf node advisory subjects.
|
||||
/// Gap 10.8: RemoteServerShutdown, RemoteServerUpdate, LeafNodeConnected events.
|
||||
/// </summary>
|
||||
public class RemoteServerEventTests
|
||||
{
|
||||
// --- RemoteServerShutdownEvent ---
|
||||
|
||||
[Fact]
|
||||
public void RemoteServerShutdownEvent_HasCorrectEventType()
|
||||
{
|
||||
RemoteServerShutdownEvent.EventType.ShouldBe("io.nats.server.advisory.v1.remote_shutdown");
|
||||
var ev = new RemoteServerShutdownEvent();
|
||||
ev.Type.ShouldBe(RemoteServerShutdownEvent.EventType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoteServerShutdownEvent_GeneratesUniqueId()
|
||||
{
|
||||
var ev1 = new RemoteServerShutdownEvent();
|
||||
var ev2 = new RemoteServerShutdownEvent();
|
||||
ev1.Id.ShouldNotBeNullOrEmpty();
|
||||
ev2.Id.ShouldNotBeNullOrEmpty();
|
||||
ev1.Id.ShouldNotBe(ev2.Id);
|
||||
}
|
||||
|
||||
// --- RemoteServerUpdateEvent ---
|
||||
|
||||
[Fact]
|
||||
public void RemoteServerUpdateEvent_HasCorrectEventType()
|
||||
{
|
||||
RemoteServerUpdateEvent.EventType.ShouldBe("io.nats.server.advisory.v1.remote_update");
|
||||
var ev = new RemoteServerUpdateEvent();
|
||||
ev.Type.ShouldBe(RemoteServerUpdateEvent.EventType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RemoteServerUpdateEvent_AllFieldsSettable()
|
||||
{
|
||||
var server = new EventServerInfo { Id = "srv1", Name = "my-server" };
|
||||
var ev = new RemoteServerUpdateEvent
|
||||
{
|
||||
Server = server,
|
||||
RemoteServerId = "remote-id-123",
|
||||
RemoteServerName = "remote-server",
|
||||
UpdateType = "routes_changed",
|
||||
};
|
||||
|
||||
ev.Server.ShouldBeSameAs(server);
|
||||
ev.RemoteServerId.ShouldBe("remote-id-123");
|
||||
ev.RemoteServerName.ShouldBe("remote-server");
|
||||
ev.UpdateType.ShouldBe("routes_changed");
|
||||
}
|
||||
|
||||
// --- LeafNodeConnectEvent ---
|
||||
|
||||
[Fact]
|
||||
public void LeafNodeConnectEvent_HasCorrectEventType()
|
||||
{
|
||||
LeafNodeConnectEvent.EventType.ShouldBe("io.nats.server.advisory.v1.leafnode_connect");
|
||||
var ev = new LeafNodeConnectEvent();
|
||||
ev.Type.ShouldBe(LeafNodeConnectEvent.EventType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LeafNodeConnectEvent_AllFieldsSettable()
|
||||
{
|
||||
var server = new EventServerInfo { Id = "srv1", Name = "hub" };
|
||||
var ev = new LeafNodeConnectEvent
|
||||
{
|
||||
Server = server,
|
||||
LeafNodeId = "leaf-id-abc",
|
||||
LeafNodeName = "leaf-node-1",
|
||||
RemoteUrl = "nats://10.0.0.1:7422",
|
||||
Account = "ACC",
|
||||
};
|
||||
|
||||
ev.Server.ShouldBeSameAs(server);
|
||||
ev.LeafNodeId.ShouldBe("leaf-id-abc");
|
||||
ev.LeafNodeName.ShouldBe("leaf-node-1");
|
||||
ev.RemoteUrl.ShouldBe("nats://10.0.0.1:7422");
|
||||
ev.Account.ShouldBe("ACC");
|
||||
}
|
||||
|
||||
// --- LeafNodeDisconnectEvent ---
|
||||
|
||||
[Fact]
|
||||
public void LeafNodeDisconnectEvent_HasCorrectEventType()
|
||||
{
|
||||
LeafNodeDisconnectEvent.EventType.ShouldBe("io.nats.server.advisory.v1.leafnode_disconnect");
|
||||
var ev = new LeafNodeDisconnectEvent();
|
||||
ev.Type.ShouldBe(LeafNodeDisconnectEvent.EventType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LeafNodeDisconnectEvent_AllFieldsSettable()
|
||||
{
|
||||
var server = new EventServerInfo { Id = "srv1", Name = "hub" };
|
||||
var ev = new LeafNodeDisconnectEvent
|
||||
{
|
||||
Server = server,
|
||||
LeafNodeId = "leaf-id-xyz",
|
||||
Reason = "connection closed",
|
||||
};
|
||||
|
||||
ev.Server.ShouldBeSameAs(server);
|
||||
ev.LeafNodeId.ShouldBe("leaf-id-xyz");
|
||||
ev.Reason.ShouldBe("connection closed");
|
||||
}
|
||||
|
||||
// --- EventSubjects ---
|
||||
|
||||
[Fact]
|
||||
public void EventSubjects_RemoteShutdown_HasPlaceholder()
|
||||
{
|
||||
EventSubjects.RemoteServerShutdown.ShouldContain("{0}");
|
||||
EventSubjects.RemoteServerUpdate.ShouldContain("{0}");
|
||||
EventSubjects.LeafNodeConnected.ShouldContain("{0}");
|
||||
EventSubjects.LeafNodeDisconnected.ShouldContain("{0}");
|
||||
|
||||
// Verify format strings produce expected subjects when formatted
|
||||
var serverId = "ABCDEF123456";
|
||||
string.Format(EventSubjects.RemoteServerShutdown, serverId)
|
||||
.ShouldBe($"$SYS.SERVER.{serverId}.REMOTE.SHUTDOWN");
|
||||
string.Format(EventSubjects.LeafNodeConnected, serverId)
|
||||
.ShouldBe($"$SYS.SERVER.{serverId}.LEAFNODE.CONNECT");
|
||||
}
|
||||
|
||||
// --- JSON serialization ---
|
||||
|
||||
[Fact]
|
||||
public void AllRemoteEvents_SerializeToJson()
|
||||
{
|
||||
var server = new EventServerInfo { Id = "srv-id", Name = "test-server" };
|
||||
|
||||
var shutdown = new RemoteServerShutdownEvent
|
||||
{
|
||||
Server = server,
|
||||
RemoteServerId = "r1",
|
||||
RemoteServerName = "remote",
|
||||
Reason = "graceful",
|
||||
};
|
||||
var shutdownJson = JsonSerializer.Serialize(shutdown);
|
||||
var shutdownDoc = JsonDocument.Parse(shutdownJson).RootElement;
|
||||
shutdownDoc.GetProperty("type").GetString().ShouldBe(RemoteServerShutdownEvent.EventType);
|
||||
shutdownDoc.GetProperty("id").GetString().ShouldNotBeNullOrEmpty();
|
||||
shutdownDoc.GetProperty("remote_server_id").GetString().ShouldBe("r1");
|
||||
shutdownDoc.GetProperty("reason").GetString().ShouldBe("graceful");
|
||||
|
||||
var update = new RemoteServerUpdateEvent
|
||||
{
|
||||
Server = server,
|
||||
RemoteServerId = "r2",
|
||||
RemoteServerName = "remote2",
|
||||
UpdateType = "config_updated",
|
||||
};
|
||||
var updateJson = JsonSerializer.Serialize(update);
|
||||
var updateDoc = JsonDocument.Parse(updateJson).RootElement;
|
||||
updateDoc.GetProperty("type").GetString().ShouldBe(RemoteServerUpdateEvent.EventType);
|
||||
updateDoc.GetProperty("update_type").GetString().ShouldBe("config_updated");
|
||||
|
||||
var connect = new LeafNodeConnectEvent
|
||||
{
|
||||
Server = server,
|
||||
LeafNodeId = "leaf1",
|
||||
LeafNodeName = "leaf-node",
|
||||
RemoteUrl = "nats://10.0.0.1:7422",
|
||||
Account = "ACC",
|
||||
};
|
||||
var connectJson = JsonSerializer.Serialize(connect);
|
||||
var connectDoc = JsonDocument.Parse(connectJson).RootElement;
|
||||
connectDoc.GetProperty("type").GetString().ShouldBe(LeafNodeConnectEvent.EventType);
|
||||
connectDoc.GetProperty("leaf_node_id").GetString().ShouldBe("leaf1");
|
||||
connectDoc.GetProperty("account").GetString().ShouldBe("ACC");
|
||||
|
||||
var disconnect = new LeafNodeDisconnectEvent
|
||||
{
|
||||
Server = server,
|
||||
LeafNodeId = "leaf1",
|
||||
Reason = "timeout",
|
||||
};
|
||||
var disconnectJson = JsonSerializer.Serialize(disconnect);
|
||||
var disconnectDoc = JsonDocument.Parse(disconnectJson).RootElement;
|
||||
disconnectDoc.GetProperty("type").GetString().ShouldBe(LeafNodeDisconnectEvent.EventType);
|
||||
disconnectDoc.GetProperty("leaf_node_id").GetString().ShouldBe("leaf1");
|
||||
disconnectDoc.GetProperty("reason").GetString().ShouldBe("timeout");
|
||||
|
||||
// Roundtrip: deserialize back and verify type field survives
|
||||
var shutdownRt = JsonSerializer.Deserialize<RemoteServerShutdownEvent>(shutdownJson);
|
||||
shutdownRt.ShouldNotBeNull();
|
||||
shutdownRt!.Type.ShouldBe(RemoteServerShutdownEvent.EventType);
|
||||
shutdownRt.RemoteServerId.ShouldBe("r1");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user