langgraph-checkpoint-postgres 2.0.1__tar.gz → 2.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {langgraph_checkpoint_postgres-2.0.1 → langgraph_checkpoint_postgres-2.0.3}/PKG-INFO +2 -2
- {langgraph_checkpoint_postgres-2.0.1 → langgraph_checkpoint_postgres-2.0.3}/langgraph/checkpoint/postgres/__init__.py +21 -6
- {langgraph_checkpoint_postgres-2.0.1 → langgraph_checkpoint_postgres-2.0.3}/langgraph/checkpoint/postgres/aio.py +20 -5
- {langgraph_checkpoint_postgres-2.0.1 → langgraph_checkpoint_postgres-2.0.3}/langgraph/checkpoint/postgres/base.py +3 -2
- {langgraph_checkpoint_postgres-2.0.1 → langgraph_checkpoint_postgres-2.0.3}/langgraph/store/postgres/aio.py +0 -1
- langgraph_checkpoint_postgres-2.0.3/langgraph/store/postgres/py.typed +0 -0
- {langgraph_checkpoint_postgres-2.0.1 → langgraph_checkpoint_postgres-2.0.3}/pyproject.toml +2 -2
- {langgraph_checkpoint_postgres-2.0.1 → langgraph_checkpoint_postgres-2.0.3}/README.md +0 -0
- {langgraph_checkpoint_postgres-2.0.1/langgraph/checkpoint → langgraph_checkpoint_postgres-2.0.3/langgraph/checkpoint/postgres}/py.typed +0 -0
- {langgraph_checkpoint_postgres-2.0.1 → langgraph_checkpoint_postgres-2.0.3}/langgraph/store/postgres/__init__.py +0 -0
- {langgraph_checkpoint_postgres-2.0.1 → langgraph_checkpoint_postgres-2.0.3}/langgraph/store/postgres/base.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: langgraph-checkpoint-postgres
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.3
|
|
4
4
|
Summary: Library with a Postgres implementation of LangGraph checkpoint saver.
|
|
5
5
|
Home-page: https://www.github.com/langchain-ai/langgraph
|
|
6
6
|
License: MIT
|
|
@@ -11,7 +11,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
-
Requires-Dist: langgraph-checkpoint (>=2.0.
|
|
14
|
+
Requires-Dist: langgraph-checkpoint (>=2.0.2,<3.0.0)
|
|
15
15
|
Requires-Dist: orjson (>=3.10.1)
|
|
16
16
|
Requires-Dist: psycopg (>=3.0.0,<4.0.0)
|
|
17
17
|
Requires-Dist: psycopg-pool (>=3.0.0,<4.0.0)
|
|
@@ -3,7 +3,7 @@ from contextlib import contextmanager
|
|
|
3
3
|
from typing import Any, Iterator, Optional, Sequence, Union
|
|
4
4
|
|
|
5
5
|
from langchain_core.runnables import RunnableConfig
|
|
6
|
-
from psycopg import Connection, Cursor, Pipeline
|
|
6
|
+
from psycopg import Capabilities, Connection, Cursor, Pipeline
|
|
7
7
|
from psycopg.errors import UndefinedTable
|
|
8
8
|
from psycopg.rows import DictRow, dict_row
|
|
9
9
|
from psycopg.types.json import Jsonb
|
|
@@ -52,6 +52,7 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
52
52
|
self.conn = conn
|
|
53
53
|
self.pipe = pipe
|
|
54
54
|
self.lock = threading.Lock()
|
|
55
|
+
self.supports_pipeline = Capabilities().has_pipeline()
|
|
55
56
|
|
|
56
57
|
@classmethod
|
|
57
58
|
@contextmanager
|
|
@@ -287,7 +288,7 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
287
288
|
>>> DB_URI = "postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable"
|
|
288
289
|
>>> with PostgresSaver.from_conn_string(DB_URI) as memory:
|
|
289
290
|
>>> config = {"configurable": {"thread_id": "1", "checkpoint_ns": ""}}
|
|
290
|
-
>>> checkpoint = {"ts": "2024-05-04T06:32:42.235444+00:00", "id": "1ef4f797-8335-6428-8001-8a1503f9b875", "
|
|
291
|
+
>>> checkpoint = {"ts": "2024-05-04T06:32:42.235444+00:00", "id": "1ef4f797-8335-6428-8001-8a1503f9b875", "channel_values": {"key": "value"}}
|
|
291
292
|
>>> saved_config = memory.put(config, checkpoint, {"source": "input", "step": 1, "writes": {"key": "value"}}, {})
|
|
292
293
|
>>> print(saved_config)
|
|
293
294
|
{'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '1ef4f797-8335-6428-8001-8a1503f9b875'}}
|
|
@@ -365,6 +366,13 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
365
366
|
|
|
366
367
|
@contextmanager
|
|
367
368
|
def _cursor(self, *, pipeline: bool = False) -> Iterator[Cursor[DictRow]]:
|
|
369
|
+
"""Create a database cursor as a context manager.
|
|
370
|
+
|
|
371
|
+
Args:
|
|
372
|
+
pipeline (bool): whether to use pipeline for the DB operations inside the context manager.
|
|
373
|
+
Will be applied regardless of whether the PostgresSaver instance was initialized with a pipeline.
|
|
374
|
+
If pipeline mode is not supported, will fall back to using transaction context manager.
|
|
375
|
+
"""
|
|
368
376
|
with _get_connection(self.conn) as conn:
|
|
369
377
|
if self.pipe:
|
|
370
378
|
# a connection in pipeline mode can be used concurrently
|
|
@@ -379,10 +387,17 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
379
387
|
elif pipeline:
|
|
380
388
|
# a connection not in pipeline mode can only be used by one
|
|
381
389
|
# thread/coroutine at a time, so we acquire a lock
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
390
|
+
if self.supports_pipeline:
|
|
391
|
+
with self.lock, conn.pipeline(), conn.cursor(
|
|
392
|
+
binary=True, row_factory=dict_row
|
|
393
|
+
) as cur:
|
|
394
|
+
yield cur
|
|
395
|
+
else:
|
|
396
|
+
# Use connection's transaction context manager when pipeline mode not supported
|
|
397
|
+
with self.lock, conn.transaction(), conn.cursor(
|
|
398
|
+
binary=True, row_factory=dict_row
|
|
399
|
+
) as cur:
|
|
400
|
+
yield cur
|
|
386
401
|
else:
|
|
387
402
|
with self.lock, conn.cursor(binary=True, row_factory=dict_row) as cur:
|
|
388
403
|
yield cur
|
|
@@ -3,7 +3,7 @@ from contextlib import asynccontextmanager
|
|
|
3
3
|
from typing import Any, AsyncIterator, Iterator, Optional, Sequence, Union
|
|
4
4
|
|
|
5
5
|
from langchain_core.runnables import RunnableConfig
|
|
6
|
-
from psycopg import AsyncConnection, AsyncCursor, AsyncPipeline
|
|
6
|
+
from psycopg import AsyncConnection, AsyncCursor, AsyncPipeline, Capabilities
|
|
7
7
|
from psycopg.errors import UndefinedTable
|
|
8
8
|
from psycopg.rows import DictRow, dict_row
|
|
9
9
|
from psycopg.types.json import Jsonb
|
|
@@ -55,6 +55,7 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
55
55
|
self.pipe = pipe
|
|
56
56
|
self.lock = asyncio.Lock()
|
|
57
57
|
self.loop = asyncio.get_running_loop()
|
|
58
|
+
self.supports_pipeline = Capabilities().has_pipeline()
|
|
58
59
|
|
|
59
60
|
@classmethod
|
|
60
61
|
@asynccontextmanager
|
|
@@ -323,6 +324,13 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
323
324
|
async def _cursor(
|
|
324
325
|
self, *, pipeline: bool = False
|
|
325
326
|
) -> AsyncIterator[AsyncCursor[DictRow]]:
|
|
327
|
+
"""Create a database cursor as a context manager.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
pipeline (bool): whether to use pipeline for the DB operations inside the context manager.
|
|
331
|
+
Will be applied regardless of whether the AsyncPostgresSaver instance was initialized with a pipeline.
|
|
332
|
+
If pipeline mode is not supported, will fall back to using transaction context manager.
|
|
333
|
+
"""
|
|
326
334
|
async with _get_connection(self.conn) as conn:
|
|
327
335
|
if self.pipe:
|
|
328
336
|
# a connection in pipeline mode can be used concurrently
|
|
@@ -337,10 +345,17 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
337
345
|
elif pipeline:
|
|
338
346
|
# a connection not in pipeline mode can only be used by one
|
|
339
347
|
# thread/coroutine at a time, so we acquire a lock
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
348
|
+
if self.supports_pipeline:
|
|
349
|
+
async with self.lock, conn.pipeline(), conn.cursor(
|
|
350
|
+
binary=True, row_factory=dict_row
|
|
351
|
+
) as cur:
|
|
352
|
+
yield cur
|
|
353
|
+
else:
|
|
354
|
+
# Use connection's transaction context manager when pipeline mode not supported
|
|
355
|
+
async with self.lock, conn.transaction(), conn.cursor(
|
|
356
|
+
binary=True, row_factory=dict_row
|
|
357
|
+
) as cur:
|
|
358
|
+
yield cur
|
|
344
359
|
else:
|
|
345
360
|
async with self.lock, conn.cursor(
|
|
346
361
|
binary=True, row_factory=dict_row
|
|
@@ -84,7 +84,7 @@ select
|
|
|
84
84
|
and cw.checkpoint_id = checkpoints.checkpoint_id
|
|
85
85
|
) as pending_writes,
|
|
86
86
|
(
|
|
87
|
-
select array_agg(array[cw.type::bytea, cw.blob] order by cw.idx)
|
|
87
|
+
select array_agg(array[cw.type::bytea, cw.blob] order by cw.task_id, cw.idx)
|
|
88
88
|
from checkpoint_writes cw
|
|
89
89
|
where cw.thread_id = checkpoints.thread_id
|
|
90
90
|
and cw.checkpoint_ns = checkpoints.checkpoint_ns
|
|
@@ -133,6 +133,7 @@ class BasePostgresSaver(BaseCheckpointSaver[str]):
|
|
|
133
133
|
INSERT_CHECKPOINT_WRITES_SQL = INSERT_CHECKPOINT_WRITES_SQL
|
|
134
134
|
|
|
135
135
|
jsonplus_serde = JsonPlusSerializer()
|
|
136
|
+
supports_pipeline: bool
|
|
136
137
|
|
|
137
138
|
def _load_checkpoint(
|
|
138
139
|
self,
|
|
@@ -249,7 +250,7 @@ class BasePostgresSaver(BaseCheckpointSaver[str]):
|
|
|
249
250
|
filter: MetadataInput,
|
|
250
251
|
before: Optional[RunnableConfig] = None,
|
|
251
252
|
) -> Tuple[str, List[Any]]:
|
|
252
|
-
"""Return WHERE clause predicates for alist() given config, filter,
|
|
253
|
+
"""Return WHERE clause predicates for alist() given config, filter, before.
|
|
253
254
|
|
|
254
255
|
This method returns a tuple of a string and a tuple of values. The string
|
|
255
256
|
is the parametered WHERE clause predicate (including the WHERE keyword):
|
|
@@ -44,7 +44,6 @@ class AsyncPostgresStore(AsyncBatchedBaseStore, BasePostgresStore[AsyncConnectio
|
|
|
44
44
|
super().__init__()
|
|
45
45
|
self._deserializer = deserializer
|
|
46
46
|
self.conn = conn
|
|
47
|
-
self.conn = conn
|
|
48
47
|
self.loop = asyncio.get_running_loop()
|
|
49
48
|
|
|
50
49
|
async def abatch(self, ops: Iterable[Op]) -> list[Result]:
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "langgraph-checkpoint-postgres"
|
|
3
|
-
version = "2.0.
|
|
3
|
+
version = "2.0.3"
|
|
4
4
|
description = "Library with a Postgres implementation of LangGraph checkpoint saver."
|
|
5
5
|
authors = []
|
|
6
6
|
license = "MIT"
|
|
@@ -10,7 +10,7 @@ packages = [{ include = "langgraph" }]
|
|
|
10
10
|
|
|
11
11
|
[tool.poetry.dependencies]
|
|
12
12
|
python = "^3.9.0,<4.0"
|
|
13
|
-
langgraph-checkpoint = "^2.0.
|
|
13
|
+
langgraph-checkpoint = "^2.0.2"
|
|
14
14
|
orjson = ">=3.10.1"
|
|
15
15
|
psycopg = "^3.0.0"
|
|
16
16
|
psycopg-pool = "^3.0.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|