refactor(r2-02): delete the dead bulkhead knob — options + parser (01/U-6); stored JSON keys become ignored unknowns
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
{ "id": 7, "subject": "S-8 dispatch layer: flip HandleWriteAsync to isIdempotent:false — RED the DriverInstanceActorResilienceWiringTests expectation first, then flip; full Runtime suite green", "status": "completed", "blockedBy": [6] },
|
||||
{ "id": 8, "subject": "S-8/P-4 invoker: cache the no-retry options snapshot once per invoker + add RecordCallStart/Complete tracker accounting to the non-idempotent arm + 2 CapabilityInvokerTests", "status": "completed", "blockedBy": [7] },
|
||||
{ "id": 9, "subject": "S-8 docs + form: fix WriteIdempotentAttribute's false 'reads via reflection' claim; note the non-idempotent production default; disable Write/Ack retry cells in the razor", "status": "completed", "blockedBy": [7, 5] },
|
||||
{ "id": 10, "subject": "U-6 delete (Core): remove BulkheadMaxConcurrent/MaxQueue from DriverResilienceOptions + parser shape/merge/doc-example; add BulkheadKeys_InStoredJson_AreIgnored (migration-free contract)", "status": "pending", "blockedBy": [2, 6] },
|
||||
{ "id": 10, "subject": "U-6 delete (Core): remove BulkheadMaxConcurrent/MaxQueue from DriverResilienceOptions + parser shape/merge/doc-example; add BulkheadKeys_InStoredJson_AreIgnored (migration-free contract)", "status": "completed", "blockedBy": [2, 6] },
|
||||
{ "id": 11, "subject": "U-6 delete (AdminUI): strip bulkhead fields from ResilienceFormModel + the two razor inputs; update ResilienceFormModelTests", "status": "pending", "blockedBy": [5, 10] },
|
||||
{ "id": 12, "subject": "U-6 doc sweep (seam xmldocs, OTOPCUA0001 message + analyzer tests, operator docs; leave migrations/WedgeDetector/historical plans) + Options_properties_are_exactly_the_pipeline_wired_set knob-inertness guard", "status": "pending", "blockedBy": [10, 11] },
|
||||
{ "id": 13, "subject": "C-7 RED tests: unknown top-level key / unknown capability / unknown per-policy field survive round-trip; malformed JSON sets ParseFailed and ToJson returns the original text", "status": "pending", "blockedBy": [11] },
|
||||
|
||||
@@ -19,15 +19,6 @@ public sealed record DriverResilienceOptions
|
||||
public IReadOnlyDictionary<DriverCapability, CapabilityPolicy> CapabilityPolicies { get; init; }
|
||||
= new Dictionary<DriverCapability, CapabilityPolicy>();
|
||||
|
||||
/// <summary>Bulkhead (max concurrent in-flight calls) for every capability. Default 32.</summary>
|
||||
public int BulkheadMaxConcurrent { get; init; } = 32;
|
||||
|
||||
/// <summary>
|
||||
/// Bulkhead queue depth. Zero = no queueing; overflow fails fast with
|
||||
/// <c>BulkheadRejectedException</c>. Default 64.
|
||||
/// </summary>
|
||||
public int BulkheadMaxQueue { get; init; } = 64;
|
||||
|
||||
/// <summary>
|
||||
/// Periodic scheduled recycle interval for Tier C out-of-process hosts, in seconds.
|
||||
/// Null (the default) = no scheduled recycle; the driver's Host process keeps running
|
||||
|
||||
@@ -13,8 +13,6 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Resilience;
|
||||
/// <para>Example JSON shape per Phase 6.1 Stream A.2:</para>
|
||||
/// <code>
|
||||
/// {
|
||||
/// "bulkheadMaxConcurrent": 16,
|
||||
/// "bulkheadMaxQueue": 64,
|
||||
/// "capabilityPolicies": {
|
||||
/// "Read": { "timeoutSeconds": 5, "retryCount": 5, "breakerFailureThreshold": 3 },
|
||||
/// "Write": { "timeoutSeconds": 5, "retryCount": 0, "breakerFailureThreshold": 5 }
|
||||
@@ -114,8 +112,6 @@ public static class DriverResilienceOptionsParser
|
||||
{
|
||||
Tier = tier,
|
||||
CapabilityPolicies = merged,
|
||||
BulkheadMaxConcurrent = shape.BulkheadMaxConcurrent ?? baseOptions.BulkheadMaxConcurrent,
|
||||
BulkheadMaxQueue = shape.BulkheadMaxQueue ?? baseOptions.BulkheadMaxQueue,
|
||||
RecycleIntervalSeconds = recycleIntervalSeconds,
|
||||
};
|
||||
}
|
||||
@@ -200,10 +196,6 @@ public static class DriverResilienceOptionsParser
|
||||
|
||||
private sealed class ResilienceConfigShape
|
||||
{
|
||||
/// <summary>Gets or sets the maximum concurrent bulkhead requests.</summary>
|
||||
public int? BulkheadMaxConcurrent { get; set; }
|
||||
/// <summary>Gets or sets the maximum bulkhead queue size.</summary>
|
||||
public int? BulkheadMaxQueue { get; set; }
|
||||
/// <summary>Gets or sets the scheduled recycle interval in seconds.</summary>
|
||||
public int? RecycleIntervalSeconds { get; set; }
|
||||
/// <summary>Gets or sets the per-capability resilience policies.</summary>
|
||||
|
||||
+15
-9
@@ -98,18 +98,23 @@ public sealed class DriverResilienceOptionsParserTests
|
||||
read.BreakerFailureThreshold.ShouldBe(tierDefault.BreakerFailureThreshold);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that bulkhead overrides are honored.</summary>
|
||||
/// <summary>
|
||||
/// 01/U-6: the deleted bulkhead knob's keys in stored JSON become ignored unknown keys — a
|
||||
/// config carrying them parses clean with no diagnostic (migration-free contract).
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void BulkheadOverrides_AreHonored()
|
||||
public void BulkheadKeys_InStoredJson_AreIgnored()
|
||||
{
|
||||
var json = """
|
||||
{ "bulkheadMaxConcurrent": 100, "bulkheadMaxQueue": 500 }
|
||||
""";
|
||||
|
||||
var options = DriverResilienceOptionsParser.ParseOrDefaults(DriverTier.B, json, out _);
|
||||
var options = DriverResilienceOptionsParser.ParseOrDefaults(DriverTier.B, json, out var diag);
|
||||
|
||||
options.BulkheadMaxConcurrent.ShouldBe(100);
|
||||
options.BulkheadMaxQueue.ShouldBe(500);
|
||||
diag.ShouldBeNull();
|
||||
// Known capabilities untouched — the stale bulkhead keys are simply ignored.
|
||||
options.Resolve(DriverCapability.Read).ShouldBe(
|
||||
DriverResilienceOptions.GetTierDefaults(DriverTier.B)[DriverCapability.Read]);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that unknown capability surfaces in diagnostic but does not fail.</summary>
|
||||
@@ -133,17 +138,18 @@ public sealed class DriverResilienceOptionsParserTests
|
||||
DriverResilienceOptions.GetTierDefaults(DriverTier.A)[DriverCapability.Read]);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that property names are case insensitive.</summary>
|
||||
/// <summary>Verifies that top-level property names are case insensitive.</summary>
|
||||
[Fact]
|
||||
public void PropertyNames_AreCaseInsensitive()
|
||||
{
|
||||
var json = """
|
||||
{ "BULKHEADMAXCONCURRENT": 42 }
|
||||
{ "RECYCLEINTERVALSECONDS": 3600 }
|
||||
""";
|
||||
|
||||
var options = DriverResilienceOptionsParser.ParseOrDefaults(DriverTier.A, json, out _);
|
||||
var options = DriverResilienceOptionsParser.ParseOrDefaults(DriverTier.C, json, out var diag);
|
||||
|
||||
options.BulkheadMaxConcurrent.ShouldBe(42);
|
||||
diag.ShouldBeNull();
|
||||
options.RecycleIntervalSeconds.ShouldBe(3600);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that capability name is case insensitive.</summary>
|
||||
|
||||
Reference in New Issue
Block a user