feat(run): startup + shutdown ping on both channels
Answers 'is it even running?' within seconds of 'atm run' — no waiting 30 min for heartbeat + no need for a live trigger to occur. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -282,6 +282,16 @@ def run_live(cfg, duration_s=None, capture_stub: bool = False) -> None:
|
|||||||
]
|
]
|
||||||
notifier = FanoutNotifier(backends, Path(cfg.dead_letter_path))
|
notifier = FanoutNotifier(backends, Path(cfg.dead_letter_path))
|
||||||
|
|
||||||
|
# Startup ping — confirms both channels work before the first bar closes.
|
||||||
|
from datetime import datetime
|
||||||
|
dur_note = f" duration={cfg.heartbeat_min:d}m heartbeat" if duration_s is None else f" duration={duration_s/3600:.2f}h"
|
||||||
|
notifier.send(Alert(
|
||||||
|
kind="heartbeat",
|
||||||
|
title="ATM started",
|
||||||
|
body=f"config={cfg.config_version}{dur_note} at {datetime.now().isoformat(timespec='seconds')}",
|
||||||
|
))
|
||||||
|
audit.log({"event": "started", "config": cfg.config_version})
|
||||||
|
|
||||||
start = time.monotonic()
|
start = time.monotonic()
|
||||||
heartbeat_due = start + cfg.heartbeat_min * 60
|
heartbeat_due = start + cfg.heartbeat_min * 60
|
||||||
levels_extractor = None
|
levels_extractor = None
|
||||||
@@ -337,6 +347,13 @@ def run_live(cfg, duration_s=None, capture_stub: bool = False) -> None:
|
|||||||
heartbeat_due = time.time() + cfg.heartbeat_min * 60
|
heartbeat_due = time.time() + cfg.heartbeat_min * 60
|
||||||
time.sleep(cfg.loop_interval_s)
|
time.sleep(cfg.loop_interval_s)
|
||||||
finally:
|
finally:
|
||||||
|
try:
|
||||||
|
notifier.send(Alert(
|
||||||
|
kind="heartbeat", title="ATM stopped",
|
||||||
|
body=f"after {time.monotonic() - start:.0f}s",
|
||||||
|
))
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
notifier.stop()
|
notifier.stop()
|
||||||
audit.close()
|
audit.close()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user