Skip to content

Commit 7798ca1

Browse files
authored
Notify on Firstrade session check failures (#97)
1 parent 36b322f commit 7798ca1

2 files changed

Lines changed: 61 additions & 4 deletions

File tree

main.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,11 @@ def _runtime_error_notification_message(exc: Exception) -> str:
6969
error_text = f"{type(exc).__name__}: {exc}"
7070
if len(error_text) > 1200:
7171
error_text = error_text[:1197] + "..."
72+
is_health_check = request.path in {"/session-check", "/probe"}
7273
if str(os.getenv("NOTIFY_LANG") or "").strip().lower().startswith("zh"):
7374
return "\n".join(
7475
(
75-
"Firstrade 策略运行失败",
76+
"Firstrade 健康检查失败" if is_health_check else "Firstrade 策略运行失败",
7677
f"服务: {os.getenv('K_SERVICE') or 'firstrade-quant-service'}",
7778
f"版本: {os.getenv('K_REVISION') or '<unknown>'}",
7879
f"路由: {request.method} {request.path}",
@@ -83,7 +84,7 @@ def _runtime_error_notification_message(exc: Exception) -> str:
8384
)
8485
return "\n".join(
8586
(
86-
"Firstrade strategy run failed",
87+
"Firstrade health check failed" if is_health_check else "Firstrade strategy run failed",
8788
f"service: {os.getenv('K_SERVICE') or 'firstrade-quant-service'}",
8889
f"revision: {os.getenv('K_REVISION') or '<unknown>'}",
8990
f"route: {request.method} {request.path}",
@@ -366,9 +367,29 @@ def session_check():
366367
try:
367368
return jsonify(run_session_check())
368369
except FirstradePlatformError as exc:
369-
return jsonify({"ok": False, "error": str(exc)}), 500
370+
notification_attempted = _notify_runtime_error(exc)
371+
return (
372+
jsonify(
373+
{
374+
"ok": False,
375+
"error": str(exc),
376+
"runtime_error_notification_attempted": notification_attempted,
377+
}
378+
),
379+
500,
380+
)
370381
except Exception as exc:
371-
return jsonify({"ok": False, "error": f"{type(exc).__name__}: {exc}"}), 500
382+
notification_attempted = _notify_runtime_error(exc)
383+
return (
384+
jsonify(
385+
{
386+
"ok": False,
387+
"error": f"{type(exc).__name__}: {exc}",
388+
"runtime_error_notification_attempted": notification_attempted,
389+
}
390+
),
391+
500,
392+
)
372393

373394

374395
@app.post("/")

tests/test_request_handling.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,13 @@ def test_session_check_endpoint_is_disabled_without_explicit_http_gate(monkeypat
7979

8080
def test_session_check_endpoint_calls_service_when_gate_enabled(monkeypatch):
8181
monkeypatch.setenv("FIRSTRADE_RUN_SESSION_CHECK_ON_HTTP", "true")
82+
sent_messages = []
8283
monkeypatch.setattr(
8384
main,
8485
"run_session_check",
8586
lambda: {"ok": True, "session_reused": True, "snapshot_persisted": True},
8687
)
88+
monkeypatch.setattr(main, "build_sender", lambda *_args, **_kwargs: sent_messages.append)
8789
client = main.app.test_client()
8890

8991
response = client.post("/session-check")
@@ -94,6 +96,40 @@ def test_session_check_endpoint_calls_service_when_gate_enabled(monkeypatch):
9496
"session_reused": True,
9597
"snapshot_persisted": True,
9698
}
99+
assert sent_messages == []
100+
101+
102+
def test_session_check_endpoint_notifies_only_on_error(monkeypatch):
103+
monkeypatch.setenv("FIRSTRADE_RUN_SESSION_CHECK_ON_HTTP", "true")
104+
monkeypatch.setenv("TELEGRAM_TOKEN", "token-1")
105+
monkeypatch.setenv("GLOBAL_TELEGRAM_CHAT_ID", "chat-1")
106+
monkeypatch.setattr(
107+
main,
108+
"run_session_check",
109+
lambda: (_ for _ in ()).throw(RuntimeError("session denied")),
110+
)
111+
sent_messages = []
112+
113+
def fake_build_sender(token, chat_id):
114+
def send(message):
115+
sent_messages.append((token, chat_id, message))
116+
117+
return send
118+
119+
monkeypatch.setattr(main, "build_sender", fake_build_sender)
120+
client = main.app.test_client()
121+
122+
response = client.post("/session-check")
123+
124+
assert response.status_code == 500
125+
payload = response.get_json()
126+
assert payload["ok"] is False
127+
assert payload["runtime_error_notification_attempted"] is True
128+
assert len(sent_messages) == 1
129+
assert sent_messages[0][0] == "token-1"
130+
assert sent_messages[0][1] == "chat-1"
131+
assert "Firstrade health check failed" in sent_messages[0][2]
132+
assert "RuntimeError: session denied" in sent_messages[0][2]
97133

98134

99135
def test_root_post_calls_strategy_cycle_when_gate_enabled(monkeypatch):

0 commit comments

Comments
 (0)