up
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-12-13 18:08:55 +02:00
parent 6e45066e37
commit f1a39c4ce3
234 changed files with 24038 additions and 6910 deletions

View File

@@ -0,0 +1,110 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StellaOps.Router.Common.Abstractions;
using StellaOps.Router.Common.Models;
using StellaOps.Router.Gateway.OpenApi;
using StellaOps.Router.Transport.InMemory;
namespace StellaOps.Router.Gateway.Services;
/// <summary>
/// Manages microservice connections and updates routing state.
/// </summary>
internal sealed class ConnectionManager : IHostedService
{
private readonly InMemoryTransportServer _transportServer;
private readonly InMemoryConnectionRegistry _connectionRegistry;
private readonly IGlobalRoutingState _routingState;
private readonly IRouterOpenApiDocumentCache? _openApiCache;
private readonly ILogger<ConnectionManager> _logger;
public ConnectionManager(
InMemoryTransportServer transportServer,
InMemoryConnectionRegistry connectionRegistry,
IGlobalRoutingState routingState,
ILogger<ConnectionManager> logger,
IRouterOpenApiDocumentCache? openApiCache = null)
{
_transportServer = transportServer;
_connectionRegistry = connectionRegistry;
_routingState = routingState;
_openApiCache = openApiCache;
_logger = logger;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
// Subscribe to transport server events
_transportServer.OnHelloReceived += HandleHelloReceivedAsync;
_transportServer.OnHeartbeatReceived += HandleHeartbeatReceivedAsync;
_transportServer.OnConnectionClosed += HandleConnectionClosedAsync;
// Start the transport server
await _transportServer.StartAsync(cancellationToken);
_logger.LogInformation("Connection manager started");
}
public async Task StopAsync(CancellationToken cancellationToken)
{
await _transportServer.StopAsync(cancellationToken);
_transportServer.OnHelloReceived -= HandleHelloReceivedAsync;
_transportServer.OnHeartbeatReceived -= HandleHeartbeatReceivedAsync;
_transportServer.OnConnectionClosed -= HandleConnectionClosedAsync;
_logger.LogInformation("Connection manager stopped");
}
private Task HandleHelloReceivedAsync(ConnectionState connectionState, HelloPayload payload)
{
_logger.LogInformation(
"Connection registered: {ConnectionId} from {ServiceName}/{Version} with {EndpointCount} endpoints, {SchemaCount} schemas",
connectionState.ConnectionId,
connectionState.Instance.ServiceName,
connectionState.Instance.Version,
connectionState.Endpoints.Count,
connectionState.Schemas.Count);
// Add the connection to the routing state
_routingState.AddConnection(connectionState);
// Start listening to this connection for frames
_transportServer.StartListeningToConnection(connectionState.ConnectionId);
// Invalidate OpenAPI cache when connections change
_openApiCache?.Invalidate();
return Task.CompletedTask;
}
private Task HandleHeartbeatReceivedAsync(ConnectionState connectionState, HeartbeatPayload payload)
{
_logger.LogDebug(
"Heartbeat received from {ConnectionId}: status={Status}",
connectionState.ConnectionId,
payload.Status);
// Update connection state
_routingState.UpdateConnection(connectionState.ConnectionId, conn =>
{
conn.Status = payload.Status;
conn.LastHeartbeatUtc = DateTime.UtcNow;
});
return Task.CompletedTask;
}
private Task HandleConnectionClosedAsync(string connectionId)
{
_logger.LogInformation("Connection closed: {ConnectionId}", connectionId);
// Remove from routing state
_routingState.RemoveConnection(connectionId);
// Invalidate OpenAPI cache when connections change
_openApiCache?.Invalidate();
return Task.CompletedTask;
}
}