"""分析事件桥 — 消费子进程 event_queue,在主进程写库""" import logging import queue import threading logger = logging.getLogger("analysis.event_bridge") _BRIDGE = None _BRIDGE_LOCK = threading.Lock() class AnalysisEventBridge(object): def __init__(self): self._thread = None self._running = False self._queues = [] self._lock = threading.Lock() self._latest = {} def register_queue(self, q): with self._lock: if q not in self._queues: self._queues.append(q) def unregister_queue(self, q): with self._lock: if q in self._queues: self._queues.remove(q) def start(self): if self._running: return self._running = True self._thread = threading.Thread(target=self._loop, name="analysis-event-bridge", daemon=True) self._thread.start() logger.info("AnalysisEventBridge 已启动") def _loop(self): while self._running: handled = False with self._lock: queues = list(self._queues) for q in queues: try: while True: msg = q.get_nowait() self._handle(msg) handled = True except queue.Empty: continue if not handled: threading.Event().wait(0.05) def _handle(self, msg): if not msg or len(msg) < 2: return kind, payload = msg[0], msg[1] try: if kind == "event": self._on_event(payload) elif kind == "touch": self._on_touch(payload) elif kind == "preview": self._on_preview(payload) except Exception as e: logger.exception("事件桥处理失败: %s", e) def _on_event(self, event): from app.services.alarm_service import write_alarm, ALARM_EVENT_TYPES etype = event.get("type", "") if etype in ALARM_EVENT_TYPES: write_alarm(event) def _on_touch(self, payload): # 已停用:不再写追踪快照 pass def _on_preview(self, payload): stream_id = payload.get("stream_id") if stream_id is None: return with self._lock: self._latest[int(stream_id)] = payload def latest_preview(self, stream_id): with self._lock: value = self._latest.get(int(stream_id)) return dict(value) if value else None def clear_preview(self, stream_id): with self._lock: self._latest.pop(int(stream_id), None) def get_event_bridge(): global _BRIDGE with _BRIDGE_LOCK: if _BRIDGE is None: _BRIDGE = AnalysisEventBridge() _BRIDGE.start() return _BRIDGE