Commit Graph
2 Commits
Author SHA1 Message Date
DrSmoothl bae9f8edb0 fix(webui): connection-diff-loop compares ONLY level — strip detail timestamps
Adversarial review caught: HttpPostAdapter.describeStatus() embeds
HH:MM:SS in 'detail' (e.g. "上次推送 14:53:01"). Every webhook delivery
rotates that string every second under any active push — and the diff
loop's raw JSON.stringify compared everything, so it published on every
500ms tick under any non-idle webhook. Net effect: SSE pushed a full
connections frame at 2 Hz, exactly the polling the loop was meant to
replace, just on the push channel.

Add an optional pickComparable projector. server.ts caller passes one
that returns { uin, nickname, adapters[{ name, kind, status }] } — the
LEVEL only, not the live-rendered detail string. The SSE handler still
ships the FULL snapshot (including detail) to the WebUI; only the diff
key is pruned.

2 new tests pin the invariant: 10 detail-only ticks → ZERO publishes; a
real status-level transition publishes exactly once. Plus a throwing-
projector isolation test. 7/7 diff-loop tests green.
2026-06-24 22:55:51 +08:00
DrSmoothl a9f5f277f1 feat(core): connection-status diff loop — publish 'connections' on change
Phase 4b. OneBot adapters expose no event-emitter for connection-state edges
(listening / connected / client-count / last-delivery), so the SSE handler
can't subscribe — without this loop a connection change would only reach the
WebUI on the 30s REST reconcile fallback.

startConnectionDiffLoop polls getConnectionStatuses() at 500ms, compares
JSON-serialised snapshots, and publishes 'connections' through the StateBus
when (and only when) it actually moves. The first SUCCESSFUL observation is
treated as a baseline (no publish): the SSE handler's sendAllInitial has
already shipped the initial snapshot to every connected client on connect.
Snapshot exceptions are isolated — the loop retries on the next tick without
clobbering the baseline.

Started once per initWebUI lifetime; lives until process exit (consistent
with the other heartbeat-style intervals like the SSE 15s keepalives).

431/431 core suite green (5 new tests cover stable=silent, change=publish,
first-observation=baseline, dispose stops, snapshot-throw isolation).
2026-06-24 22:09:13 +08:00