fix(external-system-gateway): resolve ExternalSystemGateway-015..017 — treat MaxRetries=0 as unset, scope HTTP connection cap to gateway clients, no bare trailing '?'
This commit is contained in:
@@ -40,6 +40,52 @@ public class ServiceWiringTests
|
||||
Assert.Equal(4, sockets.MaxConnectionsPerServer);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MaxConcurrentConnectionsPerSystem_IsNotAppliedToNonGatewayHttpClients()
|
||||
{
|
||||
// ExternalSystemGateway-016: the gateway's connection cap must be scoped to
|
||||
// its own per-system clients ("ExternalSystem_{name}"). It must NOT leak onto
|
||||
// unrelated HttpClient consumers in the same host process (e.g. the
|
||||
// Notification Service's OAuth2 token client) — that would silently throttle
|
||||
// and override the primary-handler configuration of another component.
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["ScadaLink:ExternalSystemGateway:MaxConcurrentConnectionsPerSystem"] = "4",
|
||||
})
|
||||
.Build();
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging();
|
||||
services.AddSingleton<IConfiguration>(config);
|
||||
services.AddSingleton(Substitute.For<IExternalSystemRepository>());
|
||||
services.AddExternalSystemGateway();
|
||||
|
||||
// A client owned by a different component, registered the way the
|
||||
// Notification Service registers its OAuth2 token client — a plain
|
||||
// AddHttpClient with no custom primary handler. Its primary handler must
|
||||
// remain the framework default (uncapped), not the gateway's SocketsHttpHandler.
|
||||
services.AddHttpClient("NotificationService_OAuth2");
|
||||
|
||||
using var provider = services.BuildServiceProvider();
|
||||
var handlerFactory = provider.GetRequiredService<IHttpMessageHandlerFactory>();
|
||||
|
||||
// The gateway's own client must still get the gateway cap.
|
||||
var gatewayPrimary = FindPrimaryHandler(handlerFactory.CreateHandler("ExternalSystem_AnySystem"));
|
||||
Assert.Equal(4, Assert.IsType<SocketsHttpHandler>(gatewayPrimary).MaxConnectionsPerServer);
|
||||
|
||||
// The unrelated component's client must NOT inherit the gateway's connection
|
||||
// cap. With ConfigureHttpClientDefaults the primary handler is a
|
||||
// SocketsHttpHandler capped at the gateway's value (the leak); with a scoped
|
||||
// registration it is the framework default whose MaxConnectionsPerServer is
|
||||
// int.MaxValue.
|
||||
var otherPrimary = FindPrimaryHandler(handlerFactory.CreateHandler("NotificationService_OAuth2"));
|
||||
if (otherPrimary is SocketsHttpHandler otherSockets)
|
||||
{
|
||||
Assert.NotEqual(4, otherSockets.MaxConnectionsPerServer);
|
||||
}
|
||||
}
|
||||
|
||||
private static HttpMessageHandler FindPrimaryHandler(HttpMessageHandler handler)
|
||||
{
|
||||
var current = handler;
|
||||
|
||||
Reference in New Issue
Block a user