# 加购、合同、返利的未捕获异常原文。 # # 短码仍写在业务原因列。本表单独提交,写失败只记日志。 from __future__ import annotations import logging from dataclasses import dataclass logger = logging.getLogger("rpa_oracle.audit") _ERROR_MAX = 4000 _INSERT_SQL = """ INSERT INTO rpa_shift_error_audit ( shift_name, biz_key, error_code, error_text ) VALUES ( :shift_name, :biz_key, :error_code, :error_text ) """ # 一条班次故障审计。shift_name 是加购、合同或返利。 @dataclass(frozen=True) class ShiftError: shift_name: str biz_key: str error_code: str error_text: str # 独立事务写入 rpa_shift_error_audit。空列表不借连接。失败只记日志。 def save_shift_errors(pool, items: list[ShiftError]) -> None: if not items: return binds = [_bind(item) for item in items] try: with pool.acquire() as conn: try: with conn.cursor() as cur: cur.executemany(_INSERT_SQL, binds) conn.commit() except Exception: _rollback(conn) logger.exception("班次故障审计写入失败") except Exception: logger.exception("班次故障审计写入失败") # 收成插入 bind。原文截到 VARCHAR2(4000)。不绑 fid,留给触发器。 def _bind(item: ShiftError) -> dict[str, str]: text = item.error_text or "" if len(text) > _ERROR_MAX: text = text[:_ERROR_MAX] return { "shift_name": item.shift_name, "biz_key": item.biz_key, "error_code": item.error_code, "error_text": text, } # 回滚当前事务。回滚本身失败则忽略。 def _rollback(conn) -> None: try: conn.rollback() except Exception: pass