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:
Joseph Doherty
2026-05-17 03:18:24 -04:00
parent 4fa6f0e774
commit da8c9f171b
7 changed files with 211 additions and 35 deletions
@@ -114,15 +114,20 @@ public class ExternalSystemClient : IExternalSystemClient
// attempt above; letting EnqueueAsync re-invoke the handler would
// dispatch the same request a second time.
//
// The per-system retry settings are passed through verbatim — a
// configured MaxRetries of 0 means "never retry" and must NOT be
// collapsed to the S&F default (ExternalSystemGateway-004).
// ExternalSystemGateway-015: the entity's MaxRetries is a non-nullable
// int whose default is 0, and the Store-and-Forward engine interprets a
// stored MaxRetries of 0 as "no limit" (retry forever) — see
// StoreAndForwardMessage.MaxRetries ("0 = no limit") and the retry-sweep
// guard `MaxRetries > 0 && ...`. Passing 0 verbatim would therefore turn
// every unconfigured cached call into an unbounded retry loop. A 0 is
// treated as "unset" and passed as null so the bounded S&F default
// applies; the RetryDelay default of TimeSpan.Zero is likewise unset.
await _storeAndForward.EnqueueAsync(
StoreAndForwardCategory.ExternalSystem,
systemName,
payload,
originInstanceName,
system.MaxRetries,
system.MaxRetries > 0 ? system.MaxRetries : null,
system.RetryDelay > TimeSpan.Zero ? system.RetryDelay : null,
attemptImmediateDelivery: false);
@@ -329,7 +334,15 @@ public class ExternalSystemClient : IExternalSystemClient
var queryString = string.Join("&",
parameters.Where(p => p.Value != null)
.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value?.ToString() ?? "")}"));
url += "?" + queryString;
// Only append "?" when the effective query string is non-empty — a method
// whose parameter values are all null produces no query string, and the
// URL must then be identical to the no-parameters case rather than ending
// in a bare "?" (ExternalSystemGateway-017).
if (queryString.Length > 0)
{
url += "?" + queryString;
}
}
return url;