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:
co-authored by
Cursor
multica-agent
parent
1c740a9d48
commit
16ba83ec01
@@ -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__":
|
||||||
|
|||||||
Reference in New Issue
Block a user