mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-19 06:23:46 +02:00
fix(control-pane): keep the canvas label and live region consistent
Two ways the outage state could mislead an operator reading either channel. The failure branch cleared the live region but left the canvas aria-label holding the counts from the last successful poll, so landing on the canvas during an outage reported stale counts. It now sets the same unavailable wording on the canvas. apply() already restores the count label on the next valid poll, and there is now a test for that. Polls run every 5000ms and are not sequenced, so a slow older request can settle after a newer one has succeeded. Its catch block then announced an outage while the canvas showed the newer counts, and the two channels contradicted each other. Each poll now takes a monotonic token and only the newest one may touch the view, so a superseded failure is dropped. The runtime test can park a response, which lets it settle an older failure after a newer success. New assertions cover the canvas label after an outage, the restored label after recovery, and the superseded-failure case. Removing the canvas reset, the token guard, or the restore in apply() each fail an assertion, and the unmutated view passes all of them. Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
This commit is contained in:
@@ -240,6 +240,14 @@ function renderControlPlaneViewHtml() {
|
||||
});
|
||||
}
|
||||
|
||||
// Wording shared by the canvas label and the live region so an outage reads
|
||||
// the same way however the operator reaches it.
|
||||
var UNAVAILABLE = 'Control-plane data is unavailable. Advisories and steering are unknown.';
|
||||
// Monotonic poll id. Polls are not sequenced, so a slow older request can
|
||||
// settle after a newer one. Only the newest poll may touch the view, which
|
||||
// stops a late failure from overwriting a newer success.
|
||||
var latestPoll = 0;
|
||||
|
||||
// Polling runs every few seconds, so only speak when the advisory and
|
||||
// steering counts actually move. Repeating an unchanged summary would talk
|
||||
// over the operator without telling them anything new.
|
||||
@@ -274,14 +282,20 @@ function renderControlPlaneViewHtml() {
|
||||
}
|
||||
|
||||
function poll() {
|
||||
var token = ++latestPoll;
|
||||
fetch('/api/control-plane').then(function (r) {
|
||||
if (!r.ok) throw new Error('Control-plane request failed');
|
||||
return r.json();
|
||||
}).then(apply).catch(function () {
|
||||
// A newer poll has already answered, so this failure is stale and must
|
||||
// not overwrite the newer counts.
|
||||
if (token !== latestPoll) return;
|
||||
document.getElementById('status').textContent = 'offline';
|
||||
// The last guidance is now stale, so replace it rather than leaving the
|
||||
// live region claiming the airspace is clear.
|
||||
announce('Control-plane data is unavailable. Advisories and steering are unknown.');
|
||||
// live region claiming the airspace is clear. The canvas label goes with
|
||||
// it, or it would still report the last successful counts.
|
||||
canvas.setAttribute('aria-label', UNAVAILABLE);
|
||||
announce(UNAVAILABLE);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user