""" 分层重试 — 部署在 orchestrator 调用者层(main.py / worker.py)。 """ import logging import os from typing import Callable from data.diff_result import VerificationRun logger = logging.getLogger(__name__) HEALING_FIXES = { "compile_error": { "detect": lambda log: "not found" in (log or "").lower(), "fix": lambda: _try_set_env( "COB_LIBRARY_PATH", "D:\\360安全浏览器下载\\GC32-BDB-SP1-rename-7z-to-exe\\lib\\gnucobol", ), }, "s0c7": { "detect": lambda log: "S0C7" in (log or ""), "fix": lambda: logger.warning("[Retry] S0C7 需要人工修正测试数据中的数值字段"), }, } def _try_set_env(key: str, value: str) -> None: """尝试设置环境变量(如果当前未设置)""" if not os.environ.get(key): os.environ[key] = value logger.info(f"[Retry] 已设置环境变量 {key}={value}") else: logger.info(f"[Retry] {key} 已存在,跳过") class RetryHandler: def __init__(self, max_heal: int = 2, max_simple: int = 3): self.max_heal = max_heal self.max_simple = max_simple self.heal_count = 0 self.simple_count = 0 self.history: list[VerificationRun] = [] def run(self, pipeline_fn: Callable[[], VerificationRun]) -> VerificationRun: while (self.heal_count + self.simple_count) < (self.max_heal + self.max_simple): vr = pipeline_fn() self.history.append(vr) if vr.status in ("PASS", "QUALITY_WARN"): vr.heal_retry = self.heal_count vr.simple_retry = self.simple_count vr.total_retry = self.heal_count + self.simple_count return vr if vr.status in ("BLOCKED", "ERROR") and self.heal_count < self.max_heal: build_log = vr.debug.get("cobol_build", {}).get("log", "") healed = False for name, fix_def in HEALING_FIXES.items(): if fix_def["detect"](build_log): fix_def["fix"]() self.heal_count += 1 healed = True logger.info( f"[Retry] 自愈修复应用: {name} " f"(heal_retry={self.heal_count})" ) break if healed: continue self.simple_count += 1 logger.info(f"[Retry] 朴素重试 (simple_retry={self.simple_count})") logger.error("[Retry] 重试次数超过上限,标记 FATAL") vr = self.history[-1] if self.history else VerificationRun( status="FATAL", exit_code=4 ) vr.status = "FATAL" vr.exit_code = 4 vr.heal_retry = self.heal_count vr.simple_retry = self.simple_count vr.total_retry = self.heal_count + self.simple_count return vr