Heartbeat · Pulse
The network's breathing — an append-only event log, a pulse worker, and the components that make its state visible at a glance.
---
.. toc::
The event log is the truth
Everything the heartbeat knows is an event: a small JSON record with a UTC timestamp, a kind (tick, task_start, task_end, api_call, error, note), a phase (idle, working, error), and a task slug. Events append to data/heartbeat/events.jsonl (never rewritten, except by the nightly prune) and mirror best-effort into Postgres.
Every dashboard number derives from this log — nothing is stored twice, so nothing can disagree. On the hub, an api_call is an outbound HTTP probe (a satellite check, the wallet-provision POST) and carries target / status / ok / latency_ms in its extras.
The dial
The HeartbeatPulse component is pure DOM + CSS — three nested rings whose animation cadence and color follow the phase:
.. exec::docs.heartbeat.pulse_examples
The rhythm bar
One cell per minute; the fill height encodes total events, the colored stack encodes kinds (error on top — the loudest thing wins the eye). Tooltips are CSS pseudo-elements, not component tooltips: 120 React portals re-rendering every second destabilized the original page, and a data-tooltip attribute costs nothing.
.. exec::docs.heartbeat.rhythm_examples
Process ownership
One environment flag decides who runs the pulse:
- Dev (no flags): the web process runs the tick loop, the job
dispatcher, everything — off shared JSONL.
- Prod: the web sets
HEARTBEAT_PULSE_WORKER=1and defers; the
2plotai-pulse sidecar owns the pulse, the APScheduler, and the dispatcher. The web reads the worker's state through the Postgres mirror — separate containers share no filesystem.
.. admonition::Truthful by construction :icon: tabler:scale :color: teal
The control board's liveness badge derives from the last tick's age in the shared log — not from any process's in-memory flag — so it tells the truth no matter which container did the ticking.
Live updates
The dashboard streams over Server-Sent Events on the FastAPI backend (/api/heartbeat/stream, owner-gated) and falls back to interval polling everywhere else. WebSocket callbacks stay off app-wide.
.. llms_copy::Heartbeat · Pulse
---
*Source: /docs/heartbeat-pulse*
Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs:
- /docs/heartbeat-pulse/llms.txt — LLM-friendly documentation
- /sitemap.xml
- /robots.txt