""" Redis 协调运行时:进程内持有客户端与常用队列句柄。 本文件职责:懒创建 / 关闭;供 Worker、llm、outbox 使用。 禁止:在 HTTP 回调里用本运行时同步等 LLM 结果。 """ from __future__ import annotations import logging import threading from dataclasses import dataclass, field from typing import Optional from agent.config import Settings, get_settings from agent.redis_coord.client import RedisClient, create_redis_client from agent.redis_coord.stream_queue import StreamQueue, llm_queue, recognition_queue logger = logging.getLogger(__name__) @dataclass class RedisRuntime: """ Redis 协调门面。 生命周期:HTTP/Worker 启动时 get_redis_runtime();退出 shutdown。 """ client: RedisClient llm_stream: StreamQueue recognition_stream: StreamQueue settings: Settings _closed: bool = field(default=False) @classmethod def create(cls, settings: Optional[Settings] = None) -> "RedisRuntime": """ 建连并准备 LLM/识别 Stream 消费组(骨架)。 副作用:ensure_group;memory 后端无外部 IO。 """ cfg = settings or get_settings() client = create_redis_client(cfg) llm = llm_queue(client) recog = recognition_queue(client) llm.ensure_group() recog.ensure_group() logger.info( "RedisRuntime 就绪 backend=%s prefix=%s", client.backend, client.key_prefix, ) return cls( client=client, llm_stream=llm, recognition_stream=recog, settings=cfg, ) def close(self) -> None: """关闭底层连接。""" if self._closed: return self.client.close() self._closed = True _runtime: Optional[RedisRuntime] = None _guard = threading.Lock() def get_redis_runtime(settings: Optional[Settings] = None) -> RedisRuntime: """进程内单例;首次创建时可能连 Redis。""" global _runtime with _guard: if _runtime is None: _runtime = RedisRuntime.create(settings) return _runtime def shutdown_redis_runtime() -> None: """进程退出时关闭。""" global _runtime with _guard: if _runtime is not None: _runtime.close() _runtime = None