fix(r2-02): enforce the spec's no-retry invariant for Write/AlarmAcknowledge overrides (01/S-8, 03/S12 layer 1)
This commit is contained in:
@@ -69,8 +69,10 @@ public sealed record DriverResilienceOptions
|
||||
|
||||
/// <summary>
|
||||
/// Per-tier per-capability default policy table, per the Phase 6.1
|
||||
/// Stream A.2 specification. Retries skipped on <see cref="DriverCapability.Write"/> and
|
||||
/// <see cref="DriverCapability.AlarmAcknowledge"/> regardless of tier.
|
||||
/// Stream A.2 specification. The parser enforces no-retry on
|
||||
/// <see cref="DriverCapability.Write"/> and <see cref="DriverCapability.AlarmAcknowledge"/>
|
||||
/// as an invariant (R2-02/S-8) — a JSON retryCount override on those capabilities is forced back
|
||||
/// to 0; per-tag opt-in via <see cref="WriteIdempotentAttribute"/> is the future relaxation.
|
||||
/// </summary>
|
||||
/// <param name="tier">The driver tier to get defaults for.</param>
|
||||
/// <returns>The default policy dictionary for the specified tier.</returns>
|
||||
|
||||
@@ -160,6 +160,18 @@ public static class DriverResilienceOptionsParser
|
||||
retry = ResiliencePolicyRanges.MaxRetryCount;
|
||||
}
|
||||
|
||||
// Spec invariant (01/S-8 = 03/S12): Write and AlarmAcknowledge are write-shaped — a duplicate is
|
||||
// not harmless (pulse coils, counter increments, Galaxy supervisory writes, alarm acks). Retries are
|
||||
// "skipped regardless of tier" per Phase 6.1; the tier defaults are already 0, so only an override can
|
||||
// differ — force it back to 0 here so the JSON→options funnel enforces the invariant. When per-tag
|
||||
// opt-in via WriteIdempotentAttribute ships, this is the one line to relax.
|
||||
if ((capability == DriverCapability.Write || capability == DriverCapability.AlarmAcknowledge) && retry > 0)
|
||||
{
|
||||
AppendDiagnostic(ref diagnostic,
|
||||
$"{capability} never retries (writes are treated as non-idempotent until per-tag opt-in ships); retryCount override ignored.");
|
||||
retry = 0;
|
||||
}
|
||||
|
||||
var breaker = merged.BreakerFailureThreshold;
|
||||
if (breaker < ResiliencePolicyRanges.MinBreakerFailureThreshold)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user