zyc fe62f9ca81
All checks were successful
Build and Deploy Log Center / build-and-deploy (push) Successful in 1m27s
fix bug
2026-02-12 13:23:59 +08:00

154 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Scheduler - 定时扫描并自动修复 Bug
"""
import signal
import threading
import time
from datetime import datetime
from typing import Optional
from loguru import logger
from ..config import settings
from .core import RepairEngine
from .task_manager import TaskManager
class RepairScheduler:
"""定时扫描 Bug 并自动触发修复"""
def __init__(
self,
interval: int = 3600,
run_tests: bool = True,
auto_commit: bool = False,
projects: Optional[list[str]] = None,
):
"""
Args:
interval: 扫描间隔(秒),默认 36001 小时)
run_tests: 修复后是否运行测试
auto_commit: 是否自动提交代码
projects: 要监控的项目列表None 表示所有已配置项目
"""
self.interval = interval
self.run_tests = run_tests
self.auto_commit = auto_commit
self.projects = projects or self._get_configured_projects()
self._stop_event = threading.Event()
self._repairing = False
@staticmethod
def _get_configured_projects() -> list[str]:
"""获取所有有路径配置的项目"""
candidates = ["rtc_backend", "rtc_web", "airhub_app"]
return [p for p in candidates if settings.get_project_path(p)]
def start(self):
"""启动定时任务阻塞式Ctrl+C 退出)"""
signal.signal(signal.SIGINT, self._handle_signal)
signal.signal(signal.SIGTERM, self._handle_signal)
logger.info("=" * 60)
logger.info("Repair Scheduler 启动")
logger.info(f" 扫描间隔: {self.interval}s ({self.interval // 60} min)")
logger.info(f" 监控项目: {', '.join(self.projects)}")
logger.info(f" 运行测试: {self.run_tests}")
logger.info(f" 自动提交: {self.auto_commit}")
logger.info("=" * 60)
# 启动后立即执行一次
self._tick()
while not self._stop_event.is_set():
self._stop_event.wait(self.interval)
if not self._stop_event.is_set():
self._tick()
logger.info("Repair Scheduler 已停止")
def stop(self):
"""停止定时任务"""
logger.info("正在停止 Scheduler...")
self._stop_event.set()
def _handle_signal(self, signum, frame):
logger.info(f"收到信号 {signum},准备停止")
self.stop()
def _tick(self):
"""执行一次扫描和修复"""
ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
logger.info(f"[{ts}] 开始扫描...")
task_manager = TaskManager()
total_found = 0
total_fixed = 0
try:
for project_id in self.projects:
bugs = task_manager.fetch_pending_bugs(project_id)
if not bugs:
logger.info(f" [{project_id}] 无待修复 Bug")
continue
count = len(bugs)
total_found += count
logger.info(f" [{project_id}] 发现 {count} 个待修复 Bug")
# 检查项目路径是否存在
project_path = settings.get_project_path(project_id)
if not project_path:
logger.warning(f" [{project_id}] 未配置项目路径,跳过")
continue
# 执行修复
fixed = self._run_repair(project_id)
total_fixed += fixed
logger.info(
f"[{ts}] 扫描完成: "
f"发现 {total_found} 个 Bug, 成功修复 {total_fixed}"
)
logger.info(f"下次扫描: {self.interval}s 后")
except Exception as e:
logger.error(f"扫描过程出错: {e}")
finally:
task_manager.close()
def _run_repair(self, project_id: str) -> int:
"""对指定项目执行修复,返回成功修复的数量"""
if self._repairing:
logger.warning(f" [{project_id}] 上一次修复尚未完成,跳过")
return 0
self._repairing = True
try:
engine = RepairEngine()
result = engine.fix_project(
project_id=project_id,
run_tests=self.run_tests,
auto_commit=self.auto_commit,
)
engine.close()
if result.total == 0:
return 0
logger.info(
f" [{project_id}] 修复结果: "
f"{result.success_count}/{result.total} 成功"
)
for r in result.results:
icon = "" if r.success else ""
logger.info(f" {icon} Bug #{r.bug_id}: {r.message}")
return result.success_count
except Exception as e:
logger.error(f" [{project_id}] 修复过程出错: {e}")
return 0
finally:
self._repairing = False