""" FAM-Core 主应用 - Flask 单进程 承载: Task-Scheduler / Dispatcher / Poller / Event-Receiver / Chat-Handler / Member-Manager / Video-Server """ import os import sys import time import threading from flask import Flask, jsonify # 确保包路径 sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from .config_loader import load_config from .logger import setup_logger from .scheduler.scheduler import TaskScheduler from .dispatcher.dispatcher import Dispatcher from .poller.poller import Poller from .event_receiver.event_receiver import event_bp from .chat_handler.chat_handler import chat_bp from .member_manager.member_manager import member_bp from .video_server.video_server import video_bp logger = setup_logger('fam-core.app') app = Flask(__name__) # 注册蓝图 app.register_blueprint(event_bp) app.register_blueprint(chat_bp) app.register_blueprint(member_bp) app.register_blueprint(video_bp) # 健康检查 @app.route('/health', methods=['GET']) def health(): return jsonify({"status": "ok", "service": "fam-core"}), 200 # 初始化后台线程 _scheduler = None _dispatcher = None _poller = None try: _scheduler = TaskScheduler() _scheduler.start() logger.info("Task-Scheduler 已启动") except Exception as e: logger.error(f"Task-Scheduler 启动失败: {e}") try: _dispatcher = Dispatcher() _dispatcher.start() logger.info("Dispatcher 已启动") except Exception as e: logger.error(f"Dispatcher 启动失败: {e}") try: _poller = Poller() _poller.start() logger.info("Poller 已启动") except Exception as e: logger.error(f"Poller 启动失败: {e}") @app.route('/api/status', methods=['GET']) def status(): """系统状态(检查线程实际存活)""" return jsonify({ "scheduler_running": _scheduler.is_alive() if _scheduler else False, "dispatcher_running": _dispatcher.is_alive() if _dispatcher else False, "poller_running": _poller.is_alive() if _poller else False, }), 200 def _watchdog_run(): """看门狗:每 60s 检查线程存活,崩溃自动重启""" logger.info("Watchdog 线程启动,检查间隔 60s") while True: time.sleep(60) for comp, name in [(_scheduler, 'Scheduler'), (_dispatcher, 'Dispatcher'), (_poller, 'Poller')]: if comp and hasattr(comp, 'check_and_restart'): try: comp.check_and_restart() except Exception as e: logger.error(f"Watchdog 重启 {name} 失败: {e}", exc_info=True) _watchdog_thread = threading.Thread(target=_watchdog_run, daemon=True, name='watchdog') _watchdog_thread.start() if __name__ == '__main__': cfg = load_config() port = cfg.get('server', {}).get('port', 8000) app.run(host='0.0.0.0', port=port, debug=False)