fix(r2-02): resilience section — parse-failure lockout + truthful raw pane (04/C-7; live-/run deferred)
This commit is contained in:
+34
-5
@@ -6,9 +6,23 @@
|
||||
<p class="form-text mb-3">Blank fields use the driver type's stability-tier defaults
|
||||
(see <span class="mono">docs/v2/driver-stability.md</span>). Set only what you need to override.</p>
|
||||
|
||||
@if (_m.ParseFailed)
|
||||
{
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<strong>Stored resilience config could not be parsed.</strong>
|
||||
Editing is locked so an accidental keystroke can't overwrite it. Fix the stored JSON directly,
|
||||
or discard it and start from tier defaults.
|
||||
<div class="mt-2">
|
||||
<button type="button" class="btn btn-sm btn-outline-danger" @onclick="DiscardAsync">
|
||||
Discard stored JSON and start blank
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4"><label class="form-label">Recycle interval (s, Tier C only)</label>
|
||||
<input type="number" class="form-control form-control-sm" @bind="_m.RecycleIntervalSeconds" @bind:after="EmitAsync" placeholder="none" /></div>
|
||||
<input type="number" class="form-control form-control-sm" @bind="_m.RecycleIntervalSeconds" @bind:after="EmitAsync" placeholder="none" disabled="@_m.ParseFailed" /></div>
|
||||
</div>
|
||||
|
||||
<div class="table-wrap mt-3">
|
||||
@@ -21,9 +35,9 @@
|
||||
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="@(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>
|
||||
<td><input type="number" class="form-control form-control-sm" @bind="row.TimeoutSeconds" @bind:after="EmitAsync" placeholder="default" disabled="@_m.ParseFailed" /></td>
|
||||
<td><input type="number" class="form-control form-control-sm" @bind="row.RetryCount" @bind:after="EmitAsync" placeholder="@(writeShaped ? "never" : "default")" disabled="@(writeShaped || _m.ParseFailed)" 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" disabled="@_m.ParseFailed" /></td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
@@ -46,7 +60,9 @@
|
||||
|
||||
<details class="mt-3">
|
||||
<summary class="small text-muted">Raw JSON (advanced)</summary>
|
||||
<pre class="form-control form-control-sm mono mt-2" style="white-space:pre-wrap;min-height:3rem;">@(_m.ToJson() ?? "(null — all tier defaults)")</pre>
|
||||
@* Render the bound STORED value, not the re-serialized model — shows the truth in both the
|
||||
healthy and the malformed case. *@
|
||||
<pre class="form-control form-control-sm mono mt-2" style="white-space:pre-wrap;min-height:3rem;">@(ResilienceConfig ?? "(null — all tier defaults)")</pre>
|
||||
</details>
|
||||
</div>
|
||||
</section>
|
||||
@@ -70,9 +86,22 @@
|
||||
|
||||
private async Task EmitAsync()
|
||||
{
|
||||
// Never emit while the stored config is unparseable — the section is locked, and an unrelated
|
||||
// keystroke must never silently overwrite what we couldn't read (04/C-7).
|
||||
if (_m.ParseFailed) return;
|
||||
|
||||
var json = _m.ToJson();
|
||||
_lastParsed = json;
|
||||
ResilienceConfig = json;
|
||||
await ResilienceConfigChanged.InvokeAsync(json);
|
||||
}
|
||||
|
||||
private async Task DiscardAsync()
|
||||
{
|
||||
// Explicit, visible destruction — replace the unparseable blob with a blank (tier-default) config.
|
||||
_m = new ResilienceFormModel();
|
||||
_lastParsed = null;
|
||||
ResilienceConfig = null;
|
||||
await ResilienceConfigChanged.InvokeAsync(null);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user