#!/usr/bin/env python3 """ Shared runner heartbeat helpers. This heartbeat is emitted by the long-running BLUE/PINK runner processes. It is intentionally separate from any Nautilus node liveness signal. """ from __future__ import annotations import json from datetime import datetime, timezone from typing import Any, Mapping RUNNER_HEARTBEAT_KEY = "runner_heartbeat" LEGACY_HEARTBEAT_KEY = "nautilus_flow_heartbeat" def build_runner_heartbeat_payload( *, flow: str, phase: str, run_date: str | None = None, runner: str | None = None, extra: Mapping[str, Any] | None = None, ) -> dict[str, Any]: payload: dict[str, Any] = { "ts": datetime.now(timezone.utc).timestamp(), "iso": datetime.now(timezone.utc).isoformat(), "phase": str(phase), "flow": str(flow), } if run_date: payload["run_date"] = str(run_date) if runner: payload["runner"] = str(runner) if extra: for key, value in extra.items(): if isinstance(key, str) and key: payload[key] = value return payload def write_runner_heartbeat( heartbeat_map: Any, payload: Mapping[str, Any], *, include_legacy_alias: bool = True, ) -> None: hb = json.dumps(dict(payload), sort_keys=True) heartbeat_map.blocking().put(RUNNER_HEARTBEAT_KEY, hb) if include_legacy_alias: heartbeat_map.blocking().put(LEGACY_HEARTBEAT_KEY, hb)