落地并存测服全端:智能体 Graph/路由、后台切 8180、主账与部署脚本齐备,便于线上重发与验收。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
"""
|
||||
进程内 inbox / outbox 队列(骨架过渡实现)。
|
||||
进程内 / PostgreSQL inbox·outbox 账本。
|
||||
|
||||
本文件职责:回调快写入队、按条认领、message_id 去重;后续可替换为 PostgreSQL 表。
|
||||
本文件职责:定义任务结构、Memory 实现、按配置选择后端工厂。
|
||||
禁止:Redis 全局 Worker 单例锁;禁止在回调线程里等 LLM。
|
||||
为何先用内存:先打通「收消息→回复」联调;落 PG 迁移不挡本迭代验收。
|
||||
有 PG_DSN 且 MESSAGE_STORE_BACKEND=postgres|auto 时用表;否则内存(本机联调)。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -15,7 +15,7 @@ import uuid
|
||||
from collections import OrderedDict
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
from agent.channel.wecom.models import InboundMessage
|
||||
|
||||
@@ -207,6 +207,7 @@ class MemoryMessageStore:
|
||||
def stats(self) -> dict[str, Any]:
|
||||
with self._lock:
|
||||
return {
|
||||
"backend": "memory",
|
||||
"inbox": len(self._inbox),
|
||||
"outbox": len(self._outbox),
|
||||
"seen_msg": len(self._seen_msg),
|
||||
@@ -218,15 +219,55 @@ class MemoryMessageStore:
|
||||
store.popitem(last=False)
|
||||
|
||||
|
||||
# 进程内单例:HTTP 回调与消费线程共享(同进程)。多进程部署时必须换 PG。
|
||||
_STORE: Optional[MemoryMessageStore] = None
|
||||
MessageStoreImpl = Union[MemoryMessageStore, Any]
|
||||
|
||||
_STORE: Optional[MessageStoreImpl] = None
|
||||
_STORE_LOCK = threading.Lock()
|
||||
|
||||
|
||||
def get_message_store() -> MemoryMessageStore:
|
||||
"""获取进程内消息账本单例。"""
|
||||
def get_message_store() -> MessageStoreImpl:
|
||||
"""
|
||||
获取消息账本单例。
|
||||
|
||||
MESSAGE_STORE_BACKEND=postgres 且 PG 可用 → PostgresMessageStore;
|
||||
auto 有 DSN 则尝试 PG,失败回退内存;memory 强制内存。
|
||||
"""
|
||||
global _STORE
|
||||
with _STORE_LOCK:
|
||||
if _STORE is None:
|
||||
_STORE = MemoryMessageStore()
|
||||
_STORE = _create_store()
|
||||
return _STORE
|
||||
|
||||
|
||||
def reset_message_store_for_tests() -> None:
|
||||
"""仅自检用:清空单例。"""
|
||||
global _STORE
|
||||
with _STORE_LOCK:
|
||||
_STORE = None
|
||||
|
||||
|
||||
def _create_store() -> MessageStoreImpl:
|
||||
from agent.config import get_settings
|
||||
|
||||
settings = get_settings()
|
||||
backend = (getattr(settings, "message_store_backend", None) or "auto").strip().lower()
|
||||
dsn = settings.resolve_pg_dsn()
|
||||
|
||||
use_pg = backend == "postgres" or (backend == "auto" and bool(dsn))
|
||||
if use_pg and dsn:
|
||||
try:
|
||||
from agent.channel.pg_store import PostgresMessageStore
|
||||
from agent.runtime_db import assert_safe_database
|
||||
|
||||
assert_safe_database(dsn)
|
||||
store = PostgresMessageStore(dsn)
|
||||
store.stats()
|
||||
logger.info("消息账本后端=postgres")
|
||||
return store
|
||||
except Exception as exc: # noqa: BLE001
|
||||
if backend == "postgres":
|
||||
raise
|
||||
logger.warning("PG 消息账本不可用,回退内存:%s", exc)
|
||||
|
||||
logger.info("消息账本后端=memory")
|
||||
return MemoryMessageStore()
|
||||
|
||||
Reference in New Issue
Block a user