Each polling page repeated its own fetch-and-set code on a fixed timer,
so a slow answer could be overtaken by the next tick, an older response
could overwrite a newer one, and nothing aborted a request when the page
went away.
usePolled skips a tick while a request is in flight, aborts on unmount
or refresh, ignores answers from dropped requests, and keeps the last
good data under an error. The alerts, hives, agents, schedules, builds,
review runs and broadcast pages and the subagent list use it.
The page opens on the firing ones. The button lists every instance again,
with the state filter and the tones back, so the table's filtering is
visible. The saved-filters key goes back to its original name, since the
state column is a filter again.
The firing-only filter and the helpers beside it move out of the page
component into a plain module, with tests for the state match, the
never-active time and the row key.
The state column stopped being a filter, so a saved "not Pending" selection
under the old key would hide every row. A new key makes the page ignore it.
The page listed every non-normal instance. It now keeps the ones in the
Alerting state and links to Grafana's alert-groups view for the pending,
no-data and error ones.
swarm-bao-grafana-controller-token, on the host that runs Grafana, logs in
to Grafana's API over its socket as the built-in admin (the password
swarm-bao-grafana-admin minted, #5138) and keeps a `swarm-controller`
service account that is an enabled Viewer. It mints a token for that
account and writes it to bao at
swarm/controller/swarm-controller/grafana/token under Grafana's leaf. A
ten-minute timer runs it again. The unit keeps a stored token Grafana
accepts. If Grafana refuses the stored token with 401, or bao holds
none, the unit deletes every token of the account and mints a new one.
Grafana's grant gains create/read/update on that leaf, and the
controller's gains read.
swarm-controller serves GET /api/alerts from Grafana's
/api/prometheus/grafana/api/v1/alerts. It reads the token from bao,
keeps it in memory, and re-reads bao once on a 401. The HTTP client has
5s connect and 15s request timeouts. Any failure is a 503 that names its
cause. swarm-ui gets an /alerts page listing them, built the same way as
the hives page.
This is option (c) on #5129, the operator's choice.