Expand description
Heartbeat / liveness progress for long-running work.
At default verbosity anodizer shows a per-artifact result line but nothing
during a step, so a legitimately slow operation — a large cargo publish,
a multi-minute asset upload over a slow link, notarytool polling Apple — is
visually indistinguishable from a hang. Two heartbeat paths close that gap,
both emitting a still … line (heartbeat_message) on a shared cadence:
- Subprocess waits go through
crate::run, whose capture loop runs arun_tickerthread. This covers every shelled-out tool — cargo, notarytool, docker, snapcraft, … - Pure-async waits (the octocrab / forge HTTP calls that never spawn a
subprocess) wrap their future in
with_heartbeat.
Both suppress at verbose (the live subprocess tee is already the progress
signal) and when the cadence env is set to 0.
Constants§
- DEFAULT_
HEARTBEAT_ INTERVAL - Default quiet period before the first heartbeat, and the cadence between subsequent ones.
- HEARTBEAT_
INTERVAL_ ENV - Env override for the heartbeat cadence, in milliseconds. The test hook: the
suite sets a few-ms interval so a heartbeat fires without a 30s wait.
0disables heartbeats entirely; a malformed value degrades to the default (heartbeats are presentation, never worth failing a run over).
Functions§
- format_
elapsed - Render
dfor a heartbeat line using the tool’s canonical compact duration spelling (45s,2m15s,1h5m) — the sameHumanDurationformat config values round-trip through, so a duration reads identically everywhere anodizer prints one. - heartbeat_
interval - Resolve the heartbeat cadence —
Nonewhen disabled (…_MS=0). - heartbeat_
message - Render one heartbeat line:
still {action} ({elapsed}). The single template both drivers print, so the line’s shape cannot drift between the subprocess ticker (action=running cargo (aarch64-…)) and the async combinator (action=uploading foo.tar.gz). - heartbeat_
period - The active heartbeat cadence for
log, orNonewhen heartbeats are off — suppressed outside Normal verbosity (StageLogger::heartbeats_enabled) or whenheartbeat_intervalis disabled. The single gate both the subprocess ticker andwith_heartbeatconsult, so the on/off policy lives in one place rather than being re-derived per driver. - run_
ticker - Run
on_tickeveryintervaluntil the pairedSendersends or is dropped, then return. The caller spawns this on whatever thread flavor it owns (a scoped thread incrate::run, an owned thread incrate::disk::FreeSpaceSampler); the sender-drop wake means shutdown is immediate — the ticker never has to wait out a residual interval. Because each emission is followed by a fresh full-interval wait, a scheduler stall can never burst a backlog of ticks: at most one fires per elapsed period. - with_
heartbeat - Await
fut, emitting aheartbeat_messageeveryheartbeat_intervaluntil it resolves, then return its output.