Repository navigation
Expand file tree
/
Copy pathcheckpointer.py
More file actions
58 lines (46 loc) · 1.63 KB
/
Copy pathcheckpointer.py
File metadata and controls
58 lines (46 loc) · 1.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
from __future__ import annotations
import asyncio
from typing import Optional
from psycopg_pool import AsyncConnectionPool
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
from src.core.config import settings
from src.core.logging_settings import logger
def build_psycopg_dsn() -> str:
return (
f"postgresql://{settings.POSTGRES_USER}:{settings.POSTGRES_PASSWORD}"
f"@{settings.POSTGRES_HOST}:{settings.POSTGRES_PORT}/{settings.POSTGRES_DB}"
)
class CheckpointerManager:
_pool: Optional[AsyncConnectionPool] = None
_saver: Optional[AsyncPostgresSaver] = None
_setup_lock: "asyncio.Lock" = asyncio.Lock()
@classmethod
async def get(cls) -> AsyncPostgresSaver:
if cls._saver is None:
async with cls._setup_lock:
if cls._saver is None:
await cls._init()
return cls._saver
@classmethod
async def _init(cls) -> None:
dsn = build_psycopg_dsn()
pool = AsyncConnectionPool(
conninfo=dsn,
kwargs={"autocommit": True},
max_size=10,
open=False,
)
await pool.open()
saver = AsyncPostgresSaver(pool)
await saver.setup()
cls._pool = pool
cls._saver = saver
logger.info("LangGraph Postgres checkpointer initialised (pool max_size=10)")
@classmethod
async def close(cls) -> None:
if cls._pool is not None:
await cls._pool.close()
cls._pool = None
cls._saver = None
logger.info("LangGraph Postgres checkpointer closed")
checkpointer_manager = CheckpointerManager