Realtime Events (SignalR)
Live updates travel over one SignalR hub at /hub/realtime. Authentication
uses the same JWT as the REST API, passed as ?access_token=<jwt> (or an
Authorization header).
Subscription groups
Section titled “Subscription groups”High-frequency streams are opt-in per group, joined only while a consuming screen is mounted and re-joined automatically on reconnect:
| Group | Carries | Consumed by |
|---|---|---|
sensors | Live sensor reading batches | Realtime Monitor |
predictions | New prediction batches | Dashboard charts |
logs | Full log stream (all levels) | LogViewer page only |
alerts | Warning/Error log entries only | Notification bell, app-wide |
The alerts group exists so warnings surface everywhere without streaming the
full logs firehose to every dashboard.
Events (server → client)
Section titled “Events (server → client)”| Event | Payload highlights |
|---|---|
SensorReading | channelIndex, value, timestamp |
NewPrediction | predictions, confidenceScores, modelId, inferenceTimeMs, window timestamps (below) |
InferenceStateChanged | state ∈ idle · ready · running, active datasource, loaded model — emitted on every lifecycle transition |
InferenceFaulted | reason, datasourceId — also raises the blocking fault banner |
HealthMetricsUpdate | CPU/GPU/memory, uptime |
ModelActivated | modelId, version, shapes, file size |
ModelUploadProgress | Upload/validation phases, error message if failed |
OutputWriteFailed | Coalesced per sink — immediate first alert, then one per 30 s window |
LogEntryAdded | Log entry (level, message, logger, metadata) |
Prediction timestamp semantics
Section titled “Prediction timestamp semantics”A prediction describes a past window of input. All timestamps are Unix epoch milliseconds from one clock — the backend stamps each sample once at read time, and that value is echoed through the pipeline, never regenerated:
| Field | Meaning |
|---|---|
windowStartTimestamp | Oldest input sample in the window |
windowEndTimestamp | Newest input sample — the “as-of” time the prediction is valid for |
timestamp | Mirrors windowEndTimestamp (compatibility) |
emittedAt | Backend wall-clock at emission — emittedAt − windowEndTimestamp ≈ end-to-end latency |
On the dashboard the prediction trace visibly trails the sensor trace by the real pipeline latency. That gap is an intended operational signal, not a rendering defect.
Delivery guarantees
Section titled “Delivery guarantees”Slow consumers never throttle inference: dashboard broadcasts are
fire-and-forget, and events to a client that can’t keep up are dropped and
counted (/api/inference/backpressure). Notification-worthy events are
deduplicated and rate-limited to keep the bell useful — see
Notifications.