落地并存测服全端:智能体 Graph/路由、后台切 8180、主账与部署脚本齐备,便于线上重发与验收。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
linmianxun
2026-09-13 21:15:58 +08:00
co-authored by Cursor
parent 0eb1adecc8
commit 8103b3b651
143 changed files with 8968 additions and 277 deletions
+50 -9
View File
@@ -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()