docs(r2-02): correct WriteIdempotentAttribute's unwired claim; disable Write/Ack retry authoring cells (S-8)

This commit is contained in:
Joseph Doherty
2026-07-13 10:07:01 -04:00
parent 20ff67bf9a
commit 99b424240a
4 changed files with 12 additions and 6 deletions
@@ -10,7 +10,7 @@
{ "id": 6, "subject": "S-8 parser layer: force Write/AlarmAcknowledge retryCount overrides to 0 with diagnostic (spec invariant, honest dead-knob surfacing) + tests + GetTierDefaults doc", "status": "completed", "blockedBy": [2] },
{ "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": "pending", "blockedBy": [7, 5] },
{ "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": 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] },
@@ -48,7 +48,10 @@ public interface IDriverCapabilityInvoker
/// Execute a <see cref="DriverCapability.Write"/> call honoring idempotence semantics — when
/// <paramref name="isIdempotent"/> is <c>false</c>, retries are disabled regardless of the
/// configured policy; when <c>true</c>, the call runs through the Write pipeline which may
/// retry if the tier configuration permits.
/// retry if the tier configuration permits. <b>The current production default is <c>false</c></b>
/// (R2-02/S-8): <c>DriverInstanceActor.HandleWriteAsync</c> passes <c>isIdempotent: false</c> so a
/// command-shaped write is never replayed; per-tag opt-in via <see cref="WriteIdempotentAttribute"/>
/// is the unshipped forward path.
/// </summary>
/// <typeparam name="TResult">Return type of the underlying driver write call.</typeparam>
/// <param name="hostName">The resolved host name for pipeline keying + status tracking.</param>
@@ -9,9 +9,11 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions;
/// <remarks>
/// Applied to tag-definition POCOs
/// (e.g. <c>ModbusTagDefinition</c>, <c>S7TagDefinition</c>, OPC UA client tag rows) at the
/// property or record level. The <c>CapabilityInvoker</c> in <c>ZB.MOM.WW.OtOpcUa.Core.Resilience</c>
/// reads this attribute via reflection once at driver-init time and caches the result; no
/// per-write reflection cost.
/// property or record level. <b>Reserved for the per-tag opt-in; NOT yet consulted</b> (R2-02/S-8) —
/// the dispatch site (<c>DriverInstanceActor.HandleWriteAsync</c>) currently treats every write as
/// non-idempotent, so no tag retries a write today. Threading tag-definition metadata to the dispatch
/// seam is the documented forward path; when it ships, the <c>CapabilityInvoker</c> non-idempotent arm
/// and the parser's Write/AlarmAcknowledge no-retry clamp are the two sites that relax.
/// </remarks>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
public sealed class WriteIdempotentAttribute : Attribute
@@ -22,10 +22,11 @@
@foreach (var cap in ResilienceFormModel.Capabilities)
{
var row = _m.Policies[cap];
var writeShaped = cap is "Write" or "AlarmAcknowledge";
<tr>
<td class="mono">@cap</td>
<td><input type="number" class="form-control form-control-sm" @bind="row.TimeoutSeconds" @bind:after="EmitAsync" placeholder="default" /></td>
<td><input type="number" class="form-control form-control-sm" @bind="row.RetryCount" @bind:after="EmitAsync" placeholder="default" /></td>
<td><input type="number" class="form-control form-control-sm" @bind="row.RetryCount" @bind:after="EmitAsync" placeholder="@(writeShaped ? "never" : "default")" disabled="@writeShaped" title="@(writeShaped ? "Writes/acks never retry — per-tag opt-in not yet available" : null)" /></td>
<td><input type="number" class="form-control form-control-sm" @bind="row.BreakerFailureThreshold" @bind:after="EmitAsync" placeholder="default" /></td>
</tr>
}