import signal import time from datetime import datetime from system_management.scheduler.task_scheduler import TaskScheduler from utils.logger import CrossPlatformLog from config import Config # 初始化日志 log = CrossPlatformLog.get_logger("Main") class IntelligenceSystem: def __init__(self, db_config=None, run_all_on_startup=False): """初始化系统(仅作为容器,不包含业务逻辑) Args: db_config: 数据库配置 run_all_on_startup: 启动时是否立即执行所有到期任务(默认False) """ self.scheduler = TaskScheduler(Config.MYSQL_CONFIG, max_workers=5) self._running = False self.run_all_on_startup = run_all_on_startup log.info(f"情报系统已初始化(Cron模式),启动时执行任务: {run_all_on_startup}") def start(self): """启动系统主入口""" self._running = True self._setup_signal_handlers() log.info("系统启动 - 运行在Cron调度模式") # 启动时执行所有到期任务(如果开关开启) if self.run_all_on_startup: print(f"\n{'='*60}") print("🚀 启动时执行所有到期任务...") print(f"{'='*60}\n") log.info("启动时执行所有到期任务") result = self.scheduler.check_and_run_tasks(print_empty_status=True) print(f"\n启动任务执行完成: 总数={result['总任务数']}, 成功={result['成功']}, 失败={result['失败']}\n") # 时间追踪变量 last_status_print_time = time.time() # 上次打印状态的时间 last_hourly_report_time = time.time() # 上次小时统计的时间 status_print_interval = 60 # 每分钟打印一次状态(60秒) hourly_report_interval = 3600 # 每小时统计一次(3600秒) try: # 主循环 - 仅负责定期检查任务 while self._running: current_time = time.time() # 判断是否需要打印状态(每分钟一次) should_print_status = (current_time - last_status_print_time) >= status_print_interval # 检查并执行到期任务 self.scheduler.check_and_run_tasks(print_empty_status=should_print_status) # 更新最后打印时间 if should_print_status: last_status_print_time = current_time # 检查是否需要进行小时统计(每小时一次) if (current_time - last_hourly_report_time) >= hourly_report_interval: self._print_hourly_stats() last_hourly_report_time = current_time # 短间隔轮询(每10秒检查一次,保证Cron时间精度) time.sleep(10) except Exception as e: log.critical("系统主循环崩溃", exc_info=True) finally: self.shutdown() def _setup_signal_handlers(self): """设置系统信号处理器""" signal.signal(signal.SIGINT, self._handle_shutdown) signal.signal(signal.SIGTERM, self._handle_shutdown) log.debug("信号处理器已注册") def _handle_shutdown(self, signum, frame): """处理系统关闭信号""" log.info(f"收到关闭信号 {signum},开始关闭系统") self._running = False def _print_hourly_stats(self): """打印并重置小时统计信息""" stats = self.scheduler.get_and_reset_hourly_stats() now = datetime.now().strftime('%Y-%m-%d %H:%M:%S') print(f"\n{'='*60}") print(f"📊 小时任务统计报告 - {now}") print(f"{'='*60}") print(f" 总任务数: {stats['总数']}") print(f" 成功: {stats['成功']}") print(f" 失败: {stats['失败']}") if stats['总数'] > 0: success_rate = (stats['成功'] / stats['总数']) * 100 print(f" 成功率: {success_rate:.1f}%") print(f"{'='*60}\n") log.info( "小时任务统计", 总任务数=stats['总数'], 成功=stats['成功'], 失败=stats['失败'] ) def shutdown(self): """优雅关闭系统""" log.info("开始优雅关闭系统") # 等待所有正在执行的任务完成 self.scheduler.executor.shutdown(wait=True, cancel_futures=False) # 记录最终状态 pending_count = self.scheduler.get_pending_tasks_count() log.info( "系统关闭完成", pending_tasks=pending_count, shutdown_time=datetime.now() ) if __name__ == "__main__": try: # 启动系统 - 仅作为入口,不包含调度逻辑 # run_all_on_startup=True: 启动时立即执行所有到期任务 # run_all_on_startup=False: 启动时不执行任务,等待下次调度周期 system = IntelligenceSystem(run_all_on_startup=False) system.start() except Exception as e: log.critical("情报系统启动失败", exc_info=True) raise