product advisories, stella router improval, tests streghthening
This commit is contained in:
@@ -35,6 +35,61 @@ public sealed class GatewayTransportOptions
|
||||
public GatewayTcpTransportOptions Tcp { get; set; } = new();
|
||||
|
||||
public GatewayTlsTransportOptions Tls { get; set; } = new();
|
||||
|
||||
public GatewayMessagingTransportOptions Messaging { get; set; } = new();
|
||||
}
|
||||
|
||||
public sealed class GatewayMessagingTransportOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether messaging (Valkey) transport is enabled.
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Valkey connection string (e.g., "localhost:6379" or "valkey:6379,password=secret").
|
||||
/// </summary>
|
||||
public string ConnectionString { get; set; } = "localhost:6379";
|
||||
|
||||
/// <summary>
|
||||
/// Valkey database number.
|
||||
/// </summary>
|
||||
public int? Database { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Queue name template for incoming requests. Use {service} placeholder.
|
||||
/// </summary>
|
||||
public string RequestQueueTemplate { get; set; } = "router:requests:{service}";
|
||||
|
||||
/// <summary>
|
||||
/// Queue name for gateway responses.
|
||||
/// </summary>
|
||||
public string ResponseQueueName { get; set; } = "router:responses";
|
||||
|
||||
/// <summary>
|
||||
/// Consumer group name for request processing.
|
||||
/// </summary>
|
||||
public string ConsumerGroup { get; set; } = "router-gateway";
|
||||
|
||||
/// <summary>
|
||||
/// Timeout for RPC requests.
|
||||
/// </summary>
|
||||
public string RequestTimeout { get; set; } = "30s";
|
||||
|
||||
/// <summary>
|
||||
/// Lease duration for message processing.
|
||||
/// </summary>
|
||||
public string LeaseDuration { get; set; } = "5m";
|
||||
|
||||
/// <summary>
|
||||
/// Batch size for leasing messages.
|
||||
/// </summary>
|
||||
public int BatchSize { get; set; } = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Heartbeat interval.
|
||||
/// </summary>
|
||||
public string HeartbeatInterval { get; set; } = "10s";
|
||||
}
|
||||
|
||||
public sealed class GatewayTcpTransportOptions
|
||||
|
||||
@@ -21,6 +21,10 @@ using StellaOps.Router.Gateway.RateLimit;
|
||||
using StellaOps.Router.Gateway.Routing;
|
||||
using StellaOps.Router.Transport.Tcp;
|
||||
using StellaOps.Router.Transport.Tls;
|
||||
using StellaOps.Router.Transport.Messaging;
|
||||
using StellaOps.Router.Transport.Messaging.Options;
|
||||
using StellaOps.Messaging.DependencyInjection;
|
||||
using StellaOps.Messaging.Transport.Valkey;
|
||||
using StellaOps.Router.AspNet;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
@@ -53,6 +57,13 @@ builder.Services.AddSingleton<GatewayMetrics>();
|
||||
builder.Services.AddTcpTransportServer();
|
||||
builder.Services.AddTlsTransportServer();
|
||||
|
||||
// Messaging transport (Valkey)
|
||||
if (bootstrapOptions.Transports.Messaging.Enabled)
|
||||
{
|
||||
builder.Services.AddMessagingTransport<ValkeyTransportPlugin>(builder.Configuration, "Gateway:Transports:Messaging");
|
||||
builder.Services.AddMessagingTransportServer();
|
||||
}
|
||||
|
||||
builder.Services.AddSingleton<GatewayTransportClient>();
|
||||
builder.Services.AddSingleton<ITransportClient>(sp => sp.GetRequiredService<GatewayTransportClient>());
|
||||
|
||||
@@ -246,4 +257,25 @@ static void ConfigureGatewayOptionsMapping(WebApplicationBuilder builder, Gatewa
|
||||
options.RequireClientCertificate = tls.RequireClientCertificate;
|
||||
options.AllowSelfSigned = tls.AllowSelfSigned;
|
||||
});
|
||||
|
||||
builder.Services.AddOptions<MessagingTransportOptions>()
|
||||
.Configure<IOptions<GatewayOptions>>((options, gateway) =>
|
||||
{
|
||||
var messaging = gateway.Value.Transports.Messaging;
|
||||
options.RequestQueueTemplate = messaging.RequestQueueTemplate;
|
||||
options.ResponseQueueName = messaging.ResponseQueueName;
|
||||
options.ConsumerGroup = messaging.ConsumerGroup;
|
||||
options.RequestTimeout = GatewayValueParser.ParseDuration(messaging.RequestTimeout, TimeSpan.FromSeconds(30));
|
||||
options.LeaseDuration = GatewayValueParser.ParseDuration(messaging.LeaseDuration, TimeSpan.FromMinutes(5));
|
||||
options.BatchSize = messaging.BatchSize;
|
||||
options.HeartbeatInterval = GatewayValueParser.ParseDuration(messaging.HeartbeatInterval, TimeSpan.FromSeconds(10));
|
||||
});
|
||||
|
||||
builder.Services.AddOptions<ValkeyTransportOptions>()
|
||||
.Configure<IOptions<GatewayOptions>>((options, gateway) =>
|
||||
{
|
||||
var messaging = gateway.Value.Transports.Messaging;
|
||||
options.ConnectionString = messaging.ConnectionString;
|
||||
options.Database = messaging.Database;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using StellaOps.Router.Common.Models;
|
||||
using StellaOps.Router.Gateway.OpenApi;
|
||||
using StellaOps.Router.Transport.Tcp;
|
||||
using StellaOps.Router.Transport.Tls;
|
||||
using StellaOps.Router.Transport.Messaging;
|
||||
|
||||
namespace StellaOps.Gateway.WebService.Services;
|
||||
|
||||
@@ -16,6 +17,7 @@ public sealed class GatewayHostedService : IHostedService
|
||||
{
|
||||
private readonly TcpTransportServer _tcpServer;
|
||||
private readonly TlsTransportServer _tlsServer;
|
||||
private readonly MessagingTransportServer? _messagingServer;
|
||||
private readonly IGlobalRoutingState _routingState;
|
||||
private readonly GatewayTransportClient _transportClient;
|
||||
private readonly IEffectiveClaimsStore _claimsStore;
|
||||
@@ -26,6 +28,7 @@ public sealed class GatewayHostedService : IHostedService
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
private bool _tcpEnabled;
|
||||
private bool _tlsEnabled;
|
||||
private bool _messagingEnabled;
|
||||
|
||||
public GatewayHostedService(
|
||||
TcpTransportServer tcpServer,
|
||||
@@ -36,10 +39,12 @@ public sealed class GatewayHostedService : IHostedService
|
||||
IOptions<GatewayOptions> options,
|
||||
GatewayServiceStatus status,
|
||||
ILogger<GatewayHostedService> logger,
|
||||
IRouterOpenApiDocumentCache? openApiCache = null)
|
||||
IRouterOpenApiDocumentCache? openApiCache = null,
|
||||
MessagingTransportServer? messagingServer = null)
|
||||
{
|
||||
_tcpServer = tcpServer;
|
||||
_tlsServer = tlsServer;
|
||||
_messagingServer = messagingServer;
|
||||
_routingState = routingState;
|
||||
_transportClient = transportClient;
|
||||
_claimsStore = claimsStore;
|
||||
@@ -59,8 +64,9 @@ public sealed class GatewayHostedService : IHostedService
|
||||
var options = _options.Value;
|
||||
_tcpEnabled = options.Transports.Tcp.Enabled;
|
||||
_tlsEnabled = options.Transports.Tls.Enabled;
|
||||
_messagingEnabled = options.Transports.Messaging.Enabled && _messagingServer is not null;
|
||||
|
||||
if (!_tcpEnabled && !_tlsEnabled)
|
||||
if (!_tcpEnabled && !_tlsEnabled && !_messagingEnabled)
|
||||
{
|
||||
_logger.LogWarning("No transports enabled; gateway will not accept microservice connections.");
|
||||
_status.MarkStarted();
|
||||
@@ -84,6 +90,17 @@ public sealed class GatewayHostedService : IHostedService
|
||||
_logger.LogInformation("TLS transport started on port {Port}", options.Transports.Tls.Port);
|
||||
}
|
||||
|
||||
if (_messagingEnabled && _messagingServer is not null)
|
||||
{
|
||||
_messagingServer.OnHelloReceived += HandleMessagingHello;
|
||||
_messagingServer.OnHeartbeatReceived += HandleMessagingHeartbeat;
|
||||
_messagingServer.OnResponseReceived += HandleMessagingResponse;
|
||||
_messagingServer.OnConnectionClosed += HandleMessagingDisconnection;
|
||||
await _messagingServer.StartAsync(cancellationToken);
|
||||
_logger.LogInformation("Messaging transport started (Valkey connection: {Connection})",
|
||||
options.Transports.Messaging.ConnectionString);
|
||||
}
|
||||
|
||||
_status.MarkStarted();
|
||||
_status.MarkReady();
|
||||
}
|
||||
@@ -110,6 +127,15 @@ public sealed class GatewayHostedService : IHostedService
|
||||
_tlsServer.OnFrame -= HandleTlsFrame;
|
||||
_tlsServer.OnDisconnection -= HandleTlsDisconnection;
|
||||
}
|
||||
|
||||
if (_messagingEnabled && _messagingServer is not null)
|
||||
{
|
||||
await _messagingServer.StopAsync(cancellationToken);
|
||||
_messagingServer.OnHelloReceived -= HandleMessagingHello;
|
||||
_messagingServer.OnHeartbeatReceived -= HandleMessagingHeartbeat;
|
||||
_messagingServer.OnResponseReceived -= HandleMessagingResponse;
|
||||
_messagingServer.OnConnectionClosed -= HandleMessagingDisconnection;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleTcpFrame(string connectionId, Frame frame)
|
||||
@@ -438,8 +464,55 @@ public sealed class GatewayHostedService : IHostedService
|
||||
{
|
||||
_tlsServer.GetConnection(connectionId)?.Close();
|
||||
}
|
||||
|
||||
// Messaging transport connections are managed by the queue system
|
||||
// and do not support explicit close operations
|
||||
}
|
||||
|
||||
#region Messaging Transport Event Handlers
|
||||
|
||||
private Task HandleMessagingHello(ConnectionState state, HelloPayload payload)
|
||||
{
|
||||
// The MessagingTransportServer already built the ConnectionState with TransportType.Messaging
|
||||
// We need to add it to the routing state and update the claims store
|
||||
_routingState.AddConnection(state);
|
||||
_claimsStore.UpdateFromMicroservice(payload.Instance.ServiceName, payload.Endpoints);
|
||||
_openApiCache?.Invalidate();
|
||||
|
||||
_logger.LogInformation(
|
||||
"Messaging connection registered: {ConnectionId} service={ServiceName} version={Version}",
|
||||
state.ConnectionId,
|
||||
state.Instance.ServiceName,
|
||||
state.Instance.Version);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task HandleMessagingHeartbeat(ConnectionState state, HeartbeatPayload payload)
|
||||
{
|
||||
_routingState.UpdateConnection(state.ConnectionId, conn =>
|
||||
{
|
||||
conn.LastHeartbeatUtc = DateTime.UtcNow;
|
||||
conn.Status = payload.Status;
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task HandleMessagingResponse(ConnectionState state, Frame frame)
|
||||
{
|
||||
_transportClient.HandleResponseFrame(frame);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task HandleMessagingDisconnection(string connectionId)
|
||||
{
|
||||
HandleDisconnect(connectionId);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private sealed class EndpointKeyComparer : IEqualityComparer<(string Method, string Path)>
|
||||
{
|
||||
public bool Equals((string Method, string Path) x, (string Method, string Path) y)
|
||||
|
||||
@@ -6,6 +6,7 @@ using StellaOps.Router.Common.Enums;
|
||||
using StellaOps.Router.Common.Models;
|
||||
using StellaOps.Router.Transport.Tcp;
|
||||
using StellaOps.Router.Transport.Tls;
|
||||
using StellaOps.Router.Transport.Messaging;
|
||||
|
||||
namespace StellaOps.Gateway.WebService.Services;
|
||||
|
||||
@@ -13,6 +14,7 @@ public sealed class GatewayTransportClient : ITransportClient
|
||||
{
|
||||
private readonly TcpTransportServer _tcpServer;
|
||||
private readonly TlsTransportServer _tlsServer;
|
||||
private readonly MessagingTransportServer? _messagingServer;
|
||||
private readonly ILogger<GatewayTransportClient> _logger;
|
||||
private readonly ConcurrentDictionary<string, TaskCompletionSource<Frame>> _pendingRequests = new();
|
||||
private readonly ConcurrentDictionary<string, Channel<Frame>> _streamingResponses = new();
|
||||
@@ -20,10 +22,12 @@ public sealed class GatewayTransportClient : ITransportClient
|
||||
public GatewayTransportClient(
|
||||
TcpTransportServer tcpServer,
|
||||
TlsTransportServer tlsServer,
|
||||
ILogger<GatewayTransportClient> logger)
|
||||
ILogger<GatewayTransportClient> logger,
|
||||
MessagingTransportServer? messagingServer = null)
|
||||
{
|
||||
_tcpServer = tcpServer;
|
||||
_tlsServer = tlsServer;
|
||||
_messagingServer = messagingServer;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -147,6 +151,13 @@ public sealed class GatewayTransportClient : ITransportClient
|
||||
case TransportType.Certificate:
|
||||
await _tlsServer.SendFrameAsync(connection.ConnectionId, frame, cancellationToken);
|
||||
break;
|
||||
case TransportType.Messaging:
|
||||
if (_messagingServer is null)
|
||||
{
|
||||
throw new InvalidOperationException("Messaging transport is not enabled");
|
||||
}
|
||||
await _messagingServer.SendToMicroserviceAsync(connection.ConnectionId, frame, cancellationToken);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException($"Transport type {connection.TransportType} is not supported by the gateway.");
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Router.Gateway\StellaOps.Router.Gateway.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Router.Transport.Tcp\StellaOps.Router.Transport.Tcp.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Router.Transport.Tls\StellaOps.Router.Transport.Tls.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Router.Transport.Messaging\StellaOps.Router.Transport.Messaging.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Messaging\StellaOps.Messaging.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Messaging.Transport.Valkey\StellaOps.Messaging.Transport.Valkey.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Auth.Security\StellaOps.Auth.Security.csproj" />
|
||||
<ProjectReference Include="..\..\__Libraries\StellaOps.Configuration\StellaOps.Configuration.csproj" />
|
||||
<ProjectReference Include="..\..\Authority\StellaOps.Authority\StellaOps.Auth.ServerIntegration\StellaOps.Auth.ServerIntegration.csproj" />
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using StellaOps.Gateway.WebService.Configuration;
|
||||
using GatewayClaimsStore = StellaOps.Gateway.WebService.Authorization.IEffectiveClaimsStore;
|
||||
using StellaOps.Gateway.WebService.Services;
|
||||
using StellaOps.Messaging;
|
||||
using StellaOps.Messaging.Abstractions;
|
||||
using StellaOps.Router.Common.Abstractions;
|
||||
using StellaOps.Router.Common.Enums;
|
||||
using StellaOps.Router.Common.Models;
|
||||
using StellaOps.Router.Transport.Messaging;
|
||||
using StellaOps.Router.Transport.Messaging.Options;
|
||||
using StellaOps.Router.Transport.Tcp;
|
||||
using StellaOps.Router.Transport.Tls;
|
||||
|
||||
namespace StellaOps.Gateway.WebService.Tests.Integration;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for the messaging transport integration in GatewayHostedService and GatewayTransportClient.
|
||||
/// These tests verify the wiring and event handling without requiring a real Valkey instance.
|
||||
/// </summary>
|
||||
public sealed class MessagingTransportIntegrationTests
|
||||
{
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
|
||||
public MessagingTransportIntegrationTests()
|
||||
{
|
||||
_jsonOptions = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
WriteIndented = false
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GatewayHostedService_CanAcceptMessagingServer()
|
||||
{
|
||||
// Arrange
|
||||
var mockQueueFactory = new Mock<IMessageQueueFactory>();
|
||||
var messagingOptions = Options.Create(new MessagingTransportOptions());
|
||||
|
||||
var messagingServer = new MessagingTransportServer(
|
||||
mockQueueFactory.Object,
|
||||
messagingOptions,
|
||||
NullLogger<MessagingTransportServer>.Instance);
|
||||
|
||||
var gatewayOptions = Options.Create(new GatewayOptions());
|
||||
|
||||
var routingState = new Mock<IGlobalRoutingState>();
|
||||
var claimsStore = new Mock<GatewayClaimsStore>();
|
||||
|
||||
var tcpOptions = Options.Create(new TcpTransportOptions { Port = 29100 });
|
||||
var tlsOptions = Options.Create(new TlsTransportOptions { Port = 29443 });
|
||||
var tcpServer = new TcpTransportServer(tcpOptions, NullLogger<TcpTransportServer>.Instance);
|
||||
var tlsServer = new TlsTransportServer(tlsOptions, NullLogger<TlsTransportServer>.Instance);
|
||||
|
||||
var transportClient = new GatewayTransportClient(
|
||||
tcpServer,
|
||||
tlsServer,
|
||||
NullLogger<GatewayTransportClient>.Instance,
|
||||
messagingServer);
|
||||
|
||||
// Act & Assert - construction should succeed with messaging server
|
||||
var hostedService = new GatewayHostedService(
|
||||
tcpServer,
|
||||
tlsServer,
|
||||
routingState.Object,
|
||||
transportClient,
|
||||
claimsStore.Object,
|
||||
gatewayOptions,
|
||||
new GatewayServiceStatus(),
|
||||
NullLogger<GatewayHostedService>.Instance,
|
||||
openApiCache: null,
|
||||
messagingServer: messagingServer);
|
||||
|
||||
Assert.NotNull(hostedService);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GatewayHostedService_CanAcceptNullMessagingServer()
|
||||
{
|
||||
// Arrange
|
||||
var gatewayOptions = Options.Create(new GatewayOptions());
|
||||
|
||||
var routingState = new Mock<IGlobalRoutingState>();
|
||||
var claimsStore = new Mock<GatewayClaimsStore>();
|
||||
|
||||
var tcpOptions = Options.Create(new TcpTransportOptions { Port = 29101 });
|
||||
var tlsOptions = Options.Create(new TlsTransportOptions { Port = 29444 });
|
||||
var tcpServer = new TcpTransportServer(tcpOptions, NullLogger<TcpTransportServer>.Instance);
|
||||
var tlsServer = new TlsTransportServer(tlsOptions, NullLogger<TlsTransportServer>.Instance);
|
||||
|
||||
var transportClient = new GatewayTransportClient(
|
||||
tcpServer,
|
||||
tlsServer,
|
||||
NullLogger<GatewayTransportClient>.Instance,
|
||||
messagingServer: null);
|
||||
|
||||
// Act & Assert - construction should succeed without messaging server
|
||||
var hostedService = new GatewayHostedService(
|
||||
tcpServer,
|
||||
tlsServer,
|
||||
routingState.Object,
|
||||
transportClient,
|
||||
claimsStore.Object,
|
||||
gatewayOptions,
|
||||
new GatewayServiceStatus(),
|
||||
NullLogger<GatewayHostedService>.Instance,
|
||||
openApiCache: null,
|
||||
messagingServer: null);
|
||||
|
||||
Assert.NotNull(hostedService);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GatewayTransportClient_WithMessagingServer_CanBeConstructed()
|
||||
{
|
||||
// Arrange
|
||||
var mockQueueFactory = new Mock<IMessageQueueFactory>();
|
||||
var messagingOptions = Options.Create(new MessagingTransportOptions());
|
||||
|
||||
var messagingServer = new MessagingTransportServer(
|
||||
mockQueueFactory.Object,
|
||||
messagingOptions,
|
||||
NullLogger<MessagingTransportServer>.Instance);
|
||||
|
||||
var tcpOptions = Options.Create(new TcpTransportOptions { Port = 29102 });
|
||||
var tlsOptions = Options.Create(new TlsTransportOptions { Port = 29445 });
|
||||
var tcpServer = new TcpTransportServer(tcpOptions, NullLogger<TcpTransportServer>.Instance);
|
||||
var tlsServer = new TlsTransportServer(tlsOptions, NullLogger<TlsTransportServer>.Instance);
|
||||
|
||||
// Act
|
||||
var transportClient = new GatewayTransportClient(
|
||||
tcpServer,
|
||||
tlsServer,
|
||||
NullLogger<GatewayTransportClient>.Instance,
|
||||
messagingServer);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(transportClient);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GatewayTransportClient_SendToMessagingConnection_ThrowsWhenServerNull()
|
||||
{
|
||||
// Arrange
|
||||
var tcpOptions = Options.Create(new TcpTransportOptions { Port = 29103 });
|
||||
var tlsOptions = Options.Create(new TlsTransportOptions { Port = 29446 });
|
||||
var tcpServer = new TcpTransportServer(tcpOptions, NullLogger<TcpTransportServer>.Instance);
|
||||
var tlsServer = new TlsTransportServer(tlsOptions, NullLogger<TlsTransportServer>.Instance);
|
||||
|
||||
// No messaging server provided
|
||||
var transportClient = new GatewayTransportClient(
|
||||
tcpServer,
|
||||
tlsServer,
|
||||
NullLogger<GatewayTransportClient>.Instance,
|
||||
messagingServer: null);
|
||||
|
||||
var connection = new ConnectionState
|
||||
{
|
||||
ConnectionId = "msg-conn-001",
|
||||
Instance = new InstanceDescriptor
|
||||
{
|
||||
InstanceId = "test-001",
|
||||
ServiceName = "test-service",
|
||||
Version = "1.0.0",
|
||||
Region = "test"
|
||||
},
|
||||
TransportType = TransportType.Messaging
|
||||
};
|
||||
|
||||
var frame = new Frame
|
||||
{
|
||||
Type = FrameType.Request,
|
||||
CorrelationId = Guid.NewGuid().ToString("N"),
|
||||
Payload = new byte[] { 1, 2, 3 }
|
||||
};
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
||||
await transportClient.SendRequestAsync(connection, frame, TimeSpan.FromSeconds(5), CancellationToken.None));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GatewayOptions_MessagingTransport_HasCorrectDefaults()
|
||||
{
|
||||
// Arrange & Act
|
||||
var options = new GatewayMessagingTransportOptions();
|
||||
|
||||
// Assert
|
||||
Assert.False(options.Enabled);
|
||||
Assert.Equal("localhost:6379", options.ConnectionString);
|
||||
Assert.Null(options.Database);
|
||||
Assert.Equal("router:requests:{service}", options.RequestQueueTemplate);
|
||||
Assert.Equal("router:responses", options.ResponseQueueName);
|
||||
Assert.Equal("router-gateway", options.ConsumerGroup);
|
||||
Assert.Equal("30s", options.RequestTimeout);
|
||||
Assert.Equal("5m", options.LeaseDuration);
|
||||
Assert.Equal(10, options.BatchSize);
|
||||
Assert.Equal("10s", options.HeartbeatInterval);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GatewayTransportOptions_IncludesMessaging()
|
||||
{
|
||||
// Arrange & Act
|
||||
var options = new GatewayTransportOptions();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(options.Tcp);
|
||||
Assert.NotNull(options.Tls);
|
||||
Assert.NotNull(options.Messaging);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,8 @@
|
||||
<ProjectReference Include="..\..\StellaOps.Gateway.WebService\StellaOps.Gateway.WebService.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Router.Gateway\StellaOps.Router.Gateway.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Router.Transport.InMemory\StellaOps.Router.Transport.InMemory.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Router.Transport.Messaging\StellaOps.Router.Transport.Messaging.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Messaging\StellaOps.Messaging.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user