Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion scripts/execution_report_heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -1187,7 +1187,8 @@ def main(now: dt.datetime | None = None) -> int:
f"Execution report heartbeat skipped for {name}: "
"no enabled runtime target matches this heartbeat"
)
_notify_normal_heartbeat(name, "No enabled runtime target matches this heartbeat; no order was submitted.")
# No report was checked, so this branch cannot claim normal execution
# or the absence of submitted orders.
return 0
lookback_hours = float(os.environ.get("RUNTIME_HEARTBEAT_LOOKBACK_HOURS") or "36")
max_reports = int(os.environ.get("RUNTIME_HEARTBEAT_MAX_REPORTS_TO_READ") or "20")
Expand Down
6 changes: 5 additions & 1 deletion scripts/runtime_heartbeat_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,12 @@ def _normalize_target(
def _load_runtime_target_items(
environ: Mapping[str, str],
) -> tuple[list[Mapping[str, Any]], Mapping[str, Any]]:
raw_runtime_target = str(environ.get("RUNTIME_TARGET_JSON") or "").strip()
raw_targets = str(environ.get("CLOUD_RUN_SERVICE_TARGETS_JSON") or "").strip()
if raw_runtime_target and str(environ.get("RUNTIME_HEARTBEAT_ACCOUNT_SCOPE") or "").strip():
# A scoped environment's current target takes precedence over the
# repository's legacy multi-target inventory.
raw_targets = ""
items: list[Mapping[str, Any]] = []
defaults: Mapping[str, Any] = {}
if raw_targets:
Expand All @@ -270,7 +275,6 @@ def _load_runtime_target_items(
)

if not items:
raw_runtime_target = str(environ.get("RUNTIME_TARGET_JSON") or "").strip()
if raw_runtime_target:
try:
runtime_target = json.loads(raw_runtime_target)
Expand Down
4 changes: 4 additions & 0 deletions tests/test_execution_report_heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,9 @@ def test_target_profile_uses_deployed_canonical_runtime_target(monkeypatch):
def test_main_skips_when_all_configured_targets_are_disabled(monkeypatch, capsys):
_clear_runtime_env(monkeypatch)
monkeypatch.setenv("RUNTIME_HEARTBEAT_NAME", "LongBridge disabled targets")
monkeypatch.setenv("RUNTIME_HEARTBEAT_NOTIFY_ON_SUCCESS", "true")
messages = []
monkeypatch.setattr(heartbeat, "_send_telegram", lambda message: messages.append(message))
monkeypatch.setenv(
"CLOUD_RUN_SERVICE_TARGETS_JSON",
json.dumps(
Expand All @@ -761,3 +764,4 @@ def test_main_skips_when_all_configured_targets_are_disabled(monkeypatch, capsys
now=dt.datetime(2026, 6, 20, 23, 10, tzinfo=dt.timezone.utc)
) == 0
assert "no enabled runtime target matches this heartbeat" in capsys.readouterr().out
assert messages == []
46 changes: 46 additions & 0 deletions tests/test_runtime_heartbeat_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,63 @@
import datetime as dt
import json

import pytest

from scripts.runtime_heartbeat_policy import (
filter_due_targets,
load_runtime_targets,
match_payload_target,
runtime_target_configuration_present,
runtime_target_configuration_has_enabled_targets,
target_key,
target_latest_due_at,
)
from scripts import execution_report_heartbeat as heartbeat


@pytest.mark.parametrize("legacy_inventory", [
[{"service": "old-sg", "account_scope": "SG", "runtime_target_enabled": False}],
[{"service": "old-paper", "account_scope": "PAPER"}],
])
def test_scoped_current_target_precedes_legacy_inventory(legacy_inventory):
environ = {
"RUNTIME_HEARTBEAT_ACCOUNT_SCOPE": "SG",
"RUNTIME_TARGET_JSON": json.dumps({
"service_name": "current-sg",
"strategy_profile": "soxl_soxx_trend_income",
"account_scope": "SG",
"live_continuity": {"state": "ACTIVE_LKG"},
}),
"CLOUD_RUN_SERVICE_TARGETS_JSON": json.dumps(legacy_inventory),
}

assert runtime_target_configuration_has_enabled_targets(environ)
targets = load_runtime_targets(environ)
assert [target["service"] for target in targets] == ["current-sg"]
assert targets[0]["strategy_profile"] == "soxl_soxx_trend_income"


def test_unscoped_heartbeat_keeps_multi_target_inventory():
environ = {
"RUNTIME_TARGET_JSON": json.dumps({"service_name": "single"}),
"CLOUD_RUN_SERVICE_TARGETS_JSON": json.dumps([
{"service": "first"}, {"service": "second"},
]),
}
assert [target["service"] for target in load_runtime_targets(environ)] == [
"first", "second",
]


def test_invalid_scoped_target_does_not_fall_back_to_legacy_inventory():
with pytest.raises(ValueError, match="RUNTIME_TARGET_JSON"):
load_runtime_targets({
"RUNTIME_HEARTBEAT_ACCOUNT_SCOPE": "SG",
"RUNTIME_TARGET_JSON": "invalid",
"CLOUD_RUN_SERVICE_TARGETS_JSON": json.dumps([{"service": "old-sg"}]),
})


def _target(
*,
service: str,
Expand Down