fix(HEL-461): 切换事务失败写入 release-group 审计日志

整组切换中断时除回滚与废弃批次外,同步记录
action=release-group 的失败审计,便于后台追踪。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
总工
2026-09-05 16:02:11 +08:00
co-authored by Cursor multica-agent
parent 1c740a9d48
commit 16ba83ec01
2 changed files with 38 additions and 1 deletions
+25 -1
View File
@@ -813,8 +813,32 @@ class Pipeline:
try: try:
self._switch_release_group(day, staged) self._switch_release_group(day, staged)
except Exception as exc: except Exception as exc:
reason = f"release group switch failed: {exc}"
for item in staged.values(): for item in staged.values():
self._abandon_batch(item["batch_id"], f"release group switch failed: {exc}") self._abandon_batch(item["batch_id"], reason)
LOGGER.warning(
"release group switch failed, previous official version keeps serving",
extra={
"hub": {
"trade_date": day,
"datasets": sorted(staged),
"reason": reason,
"event": "release_group_switch_failed",
}
},
)
self.audit(
"pipeline", "release-group", f"eod:{day}",
json.dumps(
{
"state": "failed",
"reason": reason,
"switched": [],
"force": bool(force),
},
ensure_ascii=False,
),
)
raise raise
for dataset, item in staged.items(): for dataset, item in staged.items():
results[dataset] = { results[dataset] = {
@@ -184,6 +184,13 @@ class ReleaseGroupSwitchTests(unittest.TestCase):
for table in ("eod_bars", "eod_valuation", "eod_moneyflow", "eod_auction", "eod_stocks"): for table in ("eod_bars", "eod_valuation", "eod_moneyflow", "eod_auction", "eod_stocks"):
rows = self.db.fetchall(f"SELECT * FROM {table} WHERE trade_date = ?", (TRADE_DATE,)) rows = self.db.fetchall(f"SELECT * FROM {table} WHERE trade_date = ?", (TRADE_DATE,))
self.assertEqual(rows, [], table) self.assertEqual(rows, [], table)
audit = self.db.fetchone(
"SELECT * FROM audit_log WHERE action = 'release-group' ORDER BY id DESC"
)
self.assertIsNotNone(audit)
detail = str(audit["detail"])
self.assertIn("killed mid-switch", detail)
self.assertIn("failed", detail)
def test_duplicate_runs_are_idempotent(self) -> None: def test_duplicate_runs_are_idempotent(self) -> None:
self.pipe.run_eod_batch_a(TRADE_DATE) self.pipe.run_eod_batch_a(TRADE_DATE)
@@ -389,6 +396,12 @@ class ForceBoundaryEntryTests(unittest.TestCase):
self.assertIn("killed mid-switch", ctx.exception.message) self.assertIn("killed mid-switch", ctx.exception.message)
# previous complete A/B versions keep serving # previous complete A/B versions keep serving
self.assertEqual(publications_map(self.db, TRADE_DATE), before) self.assertEqual(publications_map(self.db, TRADE_DATE), before)
audit = self.db.fetchone(
"SELECT * FROM audit_log WHERE action = 'release-group' ORDER BY id DESC"
)
self.assertIsNotNone(audit)
self.assertIn("failed", str(audit["detail"]))
self.assertIn("killed mid-switch", str(audit["detail"]))
if __name__ == "__main__": if __name__ == "__main__":