Files
inquiry_robot/inquiry-agent/agent/graph/checkpoint.py
T

92 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Checkpoint 工厂:PostgreSQL 优先,开发可降级内存。
本文件职责:按 CHECKPOINT_BACKEND / PG_DSN 创建 LangGraph checkpointer。
副作用:postgres 模式会 setup() 建 checkpoint 表(仅当前 PG_DATABASE)。
禁止:把 checkpoint 写入 Redis;禁止指向现网 ytd_runtime。
线程:Worker 进程启动时创建一次,供多槽共享(同一 thread_id 写冲突由 runtime 锁)。
"""
from __future__ import annotations
import logging
from dataclasses import dataclass
from typing import Any, Optional
from agent.config import Settings
logger = logging.getLogger(__name__)
@dataclass
class CheckpointBundle:
"""
checkpointer 与可选连接资源。
postgres 模式下保留 context/cm 以便进程退出时关闭连接池。
"""
checkpointer: Any
backend: str
_closer: Optional[Any] = None
def close(self) -> None:
"""释放 postgres 连接(若有)。无副作用于业务数据。"""
if self._closer is None:
return
try:
# from_conn_string 返回上下文管理器
self._closer.__exit__(None, None, None)
except Exception: # noqa: BLE001 — 关闭失败只记日志
logger.exception("关闭 Postgres checkpointer 失败")
self._closer = None
def create_checkpointer(settings: Settings) -> CheckpointBundle:
"""
创建 checkpointer。
- CHECKPOINT_BACKEND=memory:仅本地骨架冒烟,进程重启丢书签。
- postgres:需要可连的 resolve_pg_dsn();失败时若 ytd_env=test 可降级 memory 并打警告。
"""
backend = (settings.checkpoint_backend or "postgres").strip().lower()
if backend == "memory":
from langgraph.checkpoint.memory import MemorySaver
logger.warning("Graph checkpoint 使用 MemorySaver(仅骨架/本机;正式必须 postgres)")
return CheckpointBundle(checkpointer=MemorySaver(), backend="memory")
dsn = settings.resolve_pg_dsn()
if not dsn:
if (settings.ytd_env or "").lower() == "prod":
raise RuntimeError("正式环境必须配置 PG_DSN 或 PG_HOST/PG_DATABASE/PG_USER")
from langgraph.checkpoint.memory import MemorySaver
logger.warning(
"未配置 PG_DSN,ytd_env=%s 降级 MemorySaver;正式切流前必须接 inquiry_robot_runtime",
settings.ytd_env,
)
return CheckpointBundle(checkpointer=MemorySaver(), backend="memory")
try:
from langgraph.checkpoint.postgres import PostgresSaver
# from_conn_string 返回上下文管理器;进入后得到 saver,并需保持打开
cm = PostgresSaver.from_conn_string(dsn)
saver = cm.__enter__()
saver.setup()
logger.info(
"Graph Postgres checkpointer 就绪 database=%s",
settings.pg_database or "(from DSN)",
)
return CheckpointBundle(checkpointer=saver, backend="postgres", _closer=cm)
except Exception as exc: # noqa: BLE001
if (settings.ytd_env or "").lower() == "prod":
raise
from langgraph.checkpoint.memory import MemorySaver
logger.warning(
"Postgres checkpointer 初始化失败,降级 MemorySaver:%s",
exc,
)
return CheckpointBundle(checkpointer=MemorySaver(), backend="memory")