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.

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:

dispatcher, everything — off shared JSONL.

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: