From d7db0faa4dc8a873c3d3c889ac9e4f6cda05c68b Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 29 May 2026 11:33:29 +0800 Subject: [PATCH] fix(api): stabilize flywheel success rate window --- .../src/services/flywheel_stats_service.py | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/apps/api/src/services/flywheel_stats_service.py b/apps/api/src/services/flywheel_stats_service.py index 628b9f3a..a43a1373 100644 --- a/apps/api/src/services/flywheel_stats_service.py +++ b/apps/api/src/services/flywheel_stats_service.py @@ -241,6 +241,9 @@ class FlywheelStatsService: # 執行成功率的 source of truth 是 auto_repair_executions。 # Redis playbook success_count/failure_count 會因回寫鏈路中斷而落後, # 造成 governance / heartbeat 判定「飛輪沒有執行」。 + # 2026-05-29 Codex: + # 24h 低流量不是資料管線斷流;若 24h 未達最小樣本,改用 7d + # 穩定窗口,避免 FlywheelExecutionRateMissing 長期誤報。 try: async with get_db_context() as db: row = await db.execute( @@ -257,7 +260,22 @@ class FlywheelStatsService: if db_total_exec >= FLYWHEEL_MIN_SAMPLE: db_total_success = int(repair_stats.success or 0) return count, db_total_success / db_total_exec - if db_total_exec > 0: + + fallback_row = await db.execute( + text(""" + SELECT + COUNT(*) FILTER (WHERE success IS TRUE) AS success, + COUNT(*) AS total + FROM auto_repair_executions + WHERE created_at >= NOW() - interval '7 days' + """) + ) + fallback_stats = fallback_row.one() + fallback_total = int(fallback_stats.total or 0) + if fallback_total >= FLYWHEEL_MIN_SAMPLE: + fallback_success = int(fallback_stats.success or 0) + return count, fallback_success / fallback_total + if db_total_exec > 0 or fallback_total > 0: return count, None except Exception: logger.warning("flywheel_stats_auto_repair_execution_query_failed")