diff --git a/archreview/plans/R2-02-resilience-config-hardening-plan.md.tasks.json b/archreview/plans/R2-02-resilience-config-hardening-plan.md.tasks.json index 26510721..b04bd71d 100644 --- a/archreview/plans/R2-02-resilience-config-hardening-plan.md.tasks.json +++ b/archreview/plans/R2-02-resilience-config-hardening-plan.md.tasks.json @@ -2,7 +2,7 @@ "planPath": "archreview/plans/R2-02-resilience-config-hardening-plan.md", "tasks": [ { "id": 0, "subject": "S-6 brick-repro test (RED): parsed timeoutSeconds:0 / breakerFailureThreshold:1 must not brick capability calls — ResilienceConfigBrickTests, expect 2 failures on f6eaa267", "status": "pending", "blockedBy": [] }, - { "id": 1, "subject": "Add ResiliencePolicyRanges constants to Core.Abstractions (single source of truth for parser/builder/AdminUI, derived from Polly.Core 8.6.6 validation)", "status": "pending", "blockedBy": [] }, + { "id": 1, "subject": "Add ResiliencePolicyRanges constants to Core.Abstractions (single source of truth for parser/builder/AdminUI, derived from Polly.Core 8.6.6 validation)", "status": "completed", "blockedBy": [] }, { "id": 2, "subject": "S-6 parser: clamp timeout/retry/breaker overrides with appending diagnostics (timeout<=0 -> tier default; breaker==1 -> 2; caps) + 8 parser tests", "status": "pending", "blockedBy": [0, 1] }, { "id": 3, "subject": "S-6 builder: belt-and-braces clamp in Build so pipeline construction can never throw ValidationException + Build_NeverThrows_ForHostileDirectOptions (turns task 0 green)", "status": "pending", "blockedBy": [0, 1] }, { "id": 4, "subject": "S-6 production-wiring guard: DriverCapabilityInvokerFactory.Create with hostile JSON yields a working invoker + logged clamp diagnostic; re-run ResilienceInvokerFactoryRegistrationTests", "status": "pending", "blockedBy": [2, 3] }, diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/ResiliencePolicyRanges.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/ResiliencePolicyRanges.cs new file mode 100644 index 00000000..4fa8cb86 --- /dev/null +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/ResiliencePolicyRanges.cs @@ -0,0 +1,33 @@ +namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions; + +/// +/// Legal ranges for per-capability resilience policy values. Single source of truth shared by +/// DriverResilienceOptionsParser (clamp + diagnostic), DriverResiliencePipelineBuilder +/// (last-resort clamp so a pipeline build can never throw Polly's ValidationException), and the +/// AdminUI ResilienceFormModel (authoring-time validation messages). Derived from +/// Polly.Core 8.6.6's option validation: TimeoutStrategyOptions.Timeout ∈ [10 ms, 24 h]; +/// CircuitBreakerStrategyOptions.MinimumThroughput ≥ 2. +/// +public static class ResiliencePolicyRanges +{ + /// Minimum per-call timeout. Whole-second granularity puts the floor at 1 s (Polly's is 10 ms). + public const int MinTimeoutSeconds = 1; + + /// Maximum per-call timeout — Polly's TimeoutStrategyOptions ceiling (24 h). + public const int MaxTimeoutSeconds = 86_400; + + /// Retry floor; 0 = no retry strategy is added to the pipeline. + public const int MinRetryCount = 0; + + /// Operational retry cap (Polly itself allows int.MaxValue; 100 exponential-backoff attempts ≈ minutes). + public const int MaxRetryCount = 100; + + /// Breaker floor; 0 = no breaker strategy is added (the Tier C posture). + public const int MinBreakerFailureThreshold = 0; + + /// Polly's MinimumThroughput floor — an enabled breaker needs a threshold of at least 2. + public const int MinEnabledBreakerFailureThreshold = 2; + + /// Sanity cap on the breaker threshold (Polly has no ceiling; beyond this it can never trip in the 30 s window). + public const int MaxBreakerFailureThreshold = 10_000; +}