[阶段3] FAM-Core 瘦身为管理后台+Oracle-Sync 同步引擎,FAM-UI 改读同步镜像 - 删除 scheduler/dispatcher/poller/event_receiver/video_server,新增 oracle_sync 每30分钟拉增量写 sync_* 镜像表;member_manager/chat_handler 改走同步数据;UI 移除帧图改为事件时间线;DDL 新增 sync_videos/events/people/cursor
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
"""
|
||||
FAM-Core 主应用 - Flask 单进程
|
||||
FAM-Core 主应用 - Flask 单进程(新架构 v2)
|
||||
|
||||
承载: Task-Scheduler / Dispatcher / Poller / Event-Receiver / Chat-Handler / Member-Manager / Video-Server
|
||||
承载: Oracle-Sync(每 30 分钟拉取增量镜像)+ Member-Manager + Chat-Handler
|
||||
|
||||
NAS 不再处理视频:无 Scheduler / Dispatcher / Poller / Event-Receiver / Video-Server。
|
||||
所有视频分析在 Oracle 完成,NAS 仅作管理后台拉取展示,CPU 占用大幅降低。
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import threading
|
||||
|
||||
from flask import Flask, jsonify
|
||||
|
||||
# 确保包路径
|
||||
@@ -14,83 +16,49 @@ 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 .oracle_sync import get_sync
|
||||
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
|
||||
|
||||
# 初始化后台同步线程(NAS 唯一常驻线程)
|
||||
_sync = None
|
||||
try:
|
||||
_scheduler = TaskScheduler()
|
||||
_scheduler.start()
|
||||
logger.info("Task-Scheduler 已启动")
|
||||
_sync = get_sync()
|
||||
_sync.start()
|
||||
logger.info("Oracle-Sync 已启动")
|
||||
# 启动后立刻拉一次,前端无需等待首个周期即有数据
|
||||
try:
|
||||
_sync.trigger_now()
|
||||
logger.info("启动首次同步完成")
|
||||
except Exception as e:
|
||||
logger.warning(f"启动首次同步失败(后续周期会重试): {e}")
|
||||
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}")
|
||||
logger.error(f"Oracle-Sync 启动失败: {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,
|
||||
"service": "fam-core",
|
||||
"sync": _sync.status() if _sync else {"running": False, "error": "未初始化"},
|
||||
}), 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)
|
||||
|
||||
Reference in New Issue
Block a user