Fix router messaging re-registration stability

This commit is contained in:
master
2026-03-07 03:48:46 +02:00
parent 28932d4a85
commit 2ff0e1f86b
9 changed files with 466 additions and 116 deletions

View File

@@ -158,6 +158,56 @@ public sealed class MessagingTransportQueueOptionsTests
payload.OpenApiInfo!.Title.Should().Be("timelineindexer");
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public async Task MessagingTransportClient_ConnectAsync_WhenAlreadyConnected_ReusesQueuesAndLogicalConnection()
{
var options = Options.Create(new MessagingTransportOptions
{
ConsumerGroup = "timelineindexer-test",
BatchSize = 1
});
var queueFactory = new RecordingQueueFactory();
var client = new MessagingTransportClient(
queueFactory,
options,
NullLogger<MessagingTransportClient>.Instance);
var instance = new InstanceDescriptor
{
InstanceId = "timelineindexer-1",
ServiceName = "timelineindexer",
Version = "1.0.0",
Region = "local"
};
EndpointDescriptor[] endpoints =
[
new EndpointDescriptor
{
ServiceName = "timelineindexer",
Version = "1.0.0",
Method = "GET",
Path = "/api/v1/timeline"
}
];
await client.ConnectAsync(instance, endpoints, CancellationToken.None);
await client.ConnectAsync(instance, endpoints, CancellationToken.None);
await client.DisconnectAsync();
queueFactory.CreatedQueues.Should().HaveCount(3);
var helloMessages = queueFactory.EnqueuedMessages
.OfType<RpcRequestMessage>()
.Where(message => message.FrameType == Common.Enums.FrameType.Hello)
.ToList();
helloMessages.Should().HaveCount(2);
helloMessages.Select(message => message.ConnectionId).Distinct().Should().ContainSingle();
}
[Trait("Category", TestCategories.Unit)]
[Fact]
public void MessagingTransportOptions_DefaultControlQueue_DoesNotCollideWithGatewayServiceQueue()

View File

@@ -4,6 +4,7 @@ Source of truth: `docs/implplan/SPRINT_20260130_002_Tools_csproj_remediation_sol
| Task ID | Status | Notes |
| --- | --- | --- |
| RTR-MSG-002 | DONE | `docs/implplan/SPRINT_20260307_008_Router_integrations_messaging_reregistration_stability.md` - deterministic transport regressions now cover HELLO re-registration reuse via the xUnit v3 runner. |
| RVM-06 | DONE | Added messaging HELLO payload coverage to verify schema/openapi metadata propagation from microservice transport client. |
| REMED-05 | TODO | Remediation checklist: docs/implplan/audits/csproj-standards/remediation/checklists/src/Router/__Tests/StellaOps.Router.Common.Tests/StellaOps.Router.Common.Tests.md. |
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |

View File

@@ -0,0 +1,86 @@
using FluentAssertions;
using StellaOps.Router.Common.Enums;
using StellaOps.Router.Common.Models;
using StellaOps.Router.Gateway.State;
namespace StellaOps.Router.Gateway.Tests.Routing;
[Trait("Category", "Unit")]
public sealed class InMemoryRoutingStateTests
{
[Fact]
public void AddConnection_WhenSameInstanceReconnects_ReplacesTheStaleConnection()
{
var state = new InMemoryRoutingState();
var staleConnection = CreateConnection(
connectionId: "conn-stale",
instanceId: "integrations-1",
endpointPath: "/api/v1/integrations");
var refreshedConnection = CreateConnection(
connectionId: "conn-fresh",
instanceId: "integrations-1",
endpointPath: "/api/v1/integrations");
state.AddConnection(staleConnection);
state.AddConnection(refreshedConnection);
state.GetAllConnections().Should().ContainSingle()
.Which.ConnectionId.Should().Be("conn-fresh");
state.GetConnection("conn-stale").Should().BeNull();
state.GetConnectionsFor("integrations", "1.0.0", "GET", "/api/v1/integrations")
.Should().ContainSingle()
.Which.ConnectionId.Should().Be("conn-fresh");
}
[Fact]
public void AddConnection_WhenSameConnectionIdRefreshes_RebuildsEndpointIndexes()
{
var state = new InMemoryRoutingState();
var originalConnection = CreateConnection(
connectionId: "conn-1",
instanceId: "integrations-1",
endpointPath: "/api/v1/integrations");
var refreshedConnection = CreateConnection(
connectionId: "conn-1",
instanceId: "integrations-1",
endpointPath: "/api/v1/integrations/runtime-hosts");
state.AddConnection(originalConnection);
state.AddConnection(refreshedConnection);
state.ResolveEndpoint("GET", "/api/v1/integrations").Should().BeNull();
state.GetConnectionsFor("integrations", "1.0.0", "GET", "/api/v1/integrations/runtime-hosts")
.Should().ContainSingle()
.Which.ConnectionId.Should().Be("conn-1");
}
private static ConnectionState CreateConnection(
string connectionId,
string instanceId,
string endpointPath)
{
var endpoint = new EndpointDescriptor
{
ServiceName = "integrations",
Version = "1.0.0",
Method = "GET",
Path = endpointPath
};
var connection = new ConnectionState
{
ConnectionId = connectionId,
Instance = new InstanceDescriptor
{
InstanceId = instanceId,
ServiceName = "integrations",
Version = "1.0.0",
Region = "local"
},
TransportType = TransportType.Messaging
};
connection.Endpoints[(endpoint.Method, endpoint.Path)] = endpoint;
return connection;
}
}

View File

@@ -4,5 +4,6 @@ Source of truth: `docs/implplan/SPRINT_20260130_002_Tools_csproj_remediation_sol
| Task ID | Status | Notes |
| --- | --- | --- |
| RTR-MSG-002 | DONE | `docs/implplan/SPRINT_20260307_008_Router_integrations_messaging_reregistration_stability.md` - routing-state regressions now cover stale same-instance registration replacement and endpoint index rebuilds. |
| REMED-05 | TODO | Remediation checklist: docs/implplan/audits/csproj-standards/remediation/checklists/src/Router/__Tests/StellaOps.Router.Gateway.Tests/StellaOps.Router.Gateway.Tests.md. |
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |