langgraph-checkpoint-postgres 3.1.1__tar.gz → 3.1.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-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/.gitignore +6 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/PKG-INFO +11 -35
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/README.md +8 -32
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/checkpoint/postgres/__init__.py +24 -14
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/checkpoint/postgres/aio.py +35 -9
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/checkpoint/postgres/base.py +154 -85
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/checkpoint/postgres/shallow.py +3 -3
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/store/postgres/base.py +4 -2
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/pyproject.toml +6 -2
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/tests/test_async.py +9 -7
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/tests/test_async_store.py +64 -0
- langgraph_checkpoint_postgres-3.1.3/tests/test_conformance_delta.py +30 -0
- langgraph_checkpoint_postgres-3.1.3/tests/test_delta_pagination.py +211 -0
- langgraph_checkpoint_postgres-3.1.3/tests/test_delta_plain_value_seed.py +204 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/tests/test_store.py +49 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/uv.lock +256 -202
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/LICENSE +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/Makefile +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/checkpoint/postgres/_ainternal.py +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/checkpoint/postgres/_internal.py +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/checkpoint/postgres/py.typed +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/store/postgres/__init__.py +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/store/postgres/aio.py +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/langgraph/store/postgres/py.typed +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/tests/__init__.py +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/tests/compose-postgres.yml +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/tests/conftest.py +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/tests/embed_test_utils.py +0 -0
- {langgraph_checkpoint_postgres-3.1.1 → langgraph_checkpoint_postgres-3.1.3}/tests/test_sync.py +0 -0
|
@@ -76,7 +76,12 @@ __pypackages__/
|
|
|
76
76
|
|
|
77
77
|
# Environments
|
|
78
78
|
.env
|
|
79
|
+
.env.*
|
|
79
80
|
.envrc
|
|
81
|
+
*.crt
|
|
82
|
+
*.key
|
|
83
|
+
*.pem
|
|
84
|
+
credentials.json
|
|
80
85
|
.venv
|
|
81
86
|
.venvs
|
|
82
87
|
env/
|
|
@@ -98,6 +103,7 @@ dmypy.json
|
|
|
98
103
|
|
|
99
104
|
.vercel
|
|
100
105
|
.turbo
|
|
106
|
+
node_modules/
|
|
101
107
|
.editorconfig
|
|
102
108
|
.scratch
|
|
103
109
|
.worktrees/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: langgraph-checkpoint-postgres
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.3
|
|
4
4
|
Summary: Library with a Postgres implementation of LangGraph checkpoint saver.
|
|
5
5
|
Project-URL: Source, https://github.com/langchain-ai/langgraph/tree/main/libs/checkpoint-postgres
|
|
6
6
|
Project-URL: Twitter, https://x.com/langchain_oss
|
|
@@ -9,7 +9,7 @@ Project-URL: Reddit, https://www.reddit.com/r/LangChain/
|
|
|
9
9
|
License-Expression: MIT
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Python: >=3.10
|
|
12
|
-
Requires-Dist: langgraph-checkpoint<5.0.0,>=4.
|
|
12
|
+
Requires-Dist: langgraph-checkpoint<5.0.0,>=4.3.0
|
|
13
13
|
Requires-Dist: orjson>=3.11.5
|
|
14
14
|
Requires-Dist: psycopg-pool>=3.2.0
|
|
15
15
|
Requires-Dist: psycopg>=3.2.0
|
|
@@ -84,24 +84,12 @@ with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
|
|
|
84
84
|
"v": 4,
|
|
85
85
|
"ts": "2024-07-31T20:14:19.804150+00:00",
|
|
86
86
|
"id": "1ef4f797-8335-6428-8001-8a1503f9b875",
|
|
87
|
-
"channel_values": {
|
|
88
|
-
|
|
89
|
-
"node": "node"
|
|
90
|
-
},
|
|
91
|
-
"channel_versions": {
|
|
92
|
-
"__start__": 2,
|
|
93
|
-
"my_key": 3,
|
|
94
|
-
"start:node": 3,
|
|
95
|
-
"node": 3
|
|
96
|
-
},
|
|
87
|
+
"channel_values": {"my_key": "meow", "node": "node"},
|
|
88
|
+
"channel_versions": {"__start__": 2, "my_key": 3, "start:node": 3, "node": 3},
|
|
97
89
|
"versions_seen": {
|
|
98
90
|
"__input__": {},
|
|
99
|
-
"__start__": {
|
|
100
|
-
"
|
|
101
|
-
},
|
|
102
|
-
"node": {
|
|
103
|
-
"start:node": 2
|
|
104
|
-
}
|
|
91
|
+
"__start__": {"__start__": 1},
|
|
92
|
+
"node": {"start:node": 2},
|
|
105
93
|
},
|
|
106
94
|
}
|
|
107
95
|
|
|
@@ -125,24 +113,12 @@ async with AsyncPostgresSaver.from_conn_string(DB_URI) as checkpointer:
|
|
|
125
113
|
"v": 4,
|
|
126
114
|
"ts": "2024-07-31T20:14:19.804150+00:00",
|
|
127
115
|
"id": "1ef4f797-8335-6428-8001-8a1503f9b875",
|
|
128
|
-
"channel_values": {
|
|
129
|
-
|
|
130
|
-
"node": "node"
|
|
131
|
-
},
|
|
132
|
-
"channel_versions": {
|
|
133
|
-
"__start__": 2,
|
|
134
|
-
"my_key": 3,
|
|
135
|
-
"start:node": 3,
|
|
136
|
-
"node": 3
|
|
137
|
-
},
|
|
116
|
+
"channel_values": {"my_key": "meow", "node": "node"},
|
|
117
|
+
"channel_versions": {"__start__": 2, "my_key": 3, "start:node": 3, "node": 3},
|
|
138
118
|
"versions_seen": {
|
|
139
119
|
"__input__": {},
|
|
140
|
-
"__start__": {
|
|
141
|
-
"
|
|
142
|
-
},
|
|
143
|
-
"node": {
|
|
144
|
-
"start:node": 2
|
|
145
|
-
}
|
|
120
|
+
"__start__": {"__start__": 1},
|
|
121
|
+
"node": {"start:node": 2},
|
|
146
122
|
},
|
|
147
123
|
}
|
|
148
124
|
|
|
@@ -67,24 +67,12 @@ with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
|
|
|
67
67
|
"v": 4,
|
|
68
68
|
"ts": "2024-07-31T20:14:19.804150+00:00",
|
|
69
69
|
"id": "1ef4f797-8335-6428-8001-8a1503f9b875",
|
|
70
|
-
"channel_values": {
|
|
71
|
-
|
|
72
|
-
"node": "node"
|
|
73
|
-
},
|
|
74
|
-
"channel_versions": {
|
|
75
|
-
"__start__": 2,
|
|
76
|
-
"my_key": 3,
|
|
77
|
-
"start:node": 3,
|
|
78
|
-
"node": 3
|
|
79
|
-
},
|
|
70
|
+
"channel_values": {"my_key": "meow", "node": "node"},
|
|
71
|
+
"channel_versions": {"__start__": 2, "my_key": 3, "start:node": 3, "node": 3},
|
|
80
72
|
"versions_seen": {
|
|
81
73
|
"__input__": {},
|
|
82
|
-
"__start__": {
|
|
83
|
-
"
|
|
84
|
-
},
|
|
85
|
-
"node": {
|
|
86
|
-
"start:node": 2
|
|
87
|
-
}
|
|
74
|
+
"__start__": {"__start__": 1},
|
|
75
|
+
"node": {"start:node": 2},
|
|
88
76
|
},
|
|
89
77
|
}
|
|
90
78
|
|
|
@@ -108,24 +96,12 @@ async with AsyncPostgresSaver.from_conn_string(DB_URI) as checkpointer:
|
|
|
108
96
|
"v": 4,
|
|
109
97
|
"ts": "2024-07-31T20:14:19.804150+00:00",
|
|
110
98
|
"id": "1ef4f797-8335-6428-8001-8a1503f9b875",
|
|
111
|
-
"channel_values": {
|
|
112
|
-
|
|
113
|
-
"node": "node"
|
|
114
|
-
},
|
|
115
|
-
"channel_versions": {
|
|
116
|
-
"__start__": 2,
|
|
117
|
-
"my_key": 3,
|
|
118
|
-
"start:node": 3,
|
|
119
|
-
"node": 3
|
|
120
|
-
},
|
|
99
|
+
"channel_values": {"my_key": "meow", "node": "node"},
|
|
100
|
+
"channel_versions": {"__start__": 2, "my_key": 3, "start:node": 3, "node": 3},
|
|
121
101
|
"versions_seen": {
|
|
122
102
|
"__input__": {},
|
|
123
|
-
"__start__": {
|
|
124
|
-
"
|
|
125
|
-
},
|
|
126
|
-
"node": {
|
|
127
|
-
"start:node": 2
|
|
128
|
-
}
|
|
103
|
+
"__start__": {"__start__": 1},
|
|
104
|
+
"node": {"start:node": 2},
|
|
129
105
|
},
|
|
130
106
|
}
|
|
131
107
|
|
|
@@ -223,7 +223,7 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
223
223
|
>>> checkpoint_tuple = memory.get_tuple(config)
|
|
224
224
|
>>> print(checkpoint_tuple)
|
|
225
225
|
CheckpointTuple(...)
|
|
226
|
-
"""
|
|
226
|
+
"""
|
|
227
227
|
thread_id = config["configurable"]["thread_id"]
|
|
228
228
|
checkpoint_id = get_checkpoint_id(config)
|
|
229
229
|
checkpoint_ns = config["configurable"].get("checkpoint_ns", "")
|
|
@@ -448,11 +448,13 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
448
448
|
|
|
449
449
|
Two-stage query, both stages cover ALL requested channels:
|
|
450
450
|
|
|
451
|
-
* Stage 1 (paged): dynamic SELECT over `checkpoints` with
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
451
|
+
* Stage 1 (paged): dynamic SELECT over `checkpoints` with three
|
|
452
|
+
columns per channel: its version, an `EXISTS` probe for a stored
|
|
453
|
+
blob at that version, and its inline value. Pages newest-first by
|
|
454
|
+
`checkpoint_id`, starting at the target; page size is
|
|
455
|
+
`_DELTA_PAGE_SIZE`.
|
|
456
|
+
Stops paging when every channel has found its seed or a page comes
|
|
457
|
+
back short.
|
|
456
458
|
|
|
457
459
|
* Stage 2 (per-channel UNION ALL): one branch per channel reading
|
|
458
460
|
`checkpoint_writes` filtered to that channel's specific
|
|
@@ -467,7 +469,7 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
467
469
|
thread_id = config["configurable"]["thread_id"]
|
|
468
470
|
checkpoint_ns = config["configurable"].get("checkpoint_ns", "")
|
|
469
471
|
checkpoint_id = get_checkpoint_id(config)
|
|
470
|
-
if checkpoint_id
|
|
472
|
+
if not checkpoint_id:
|
|
471
473
|
target = self.get_tuple(config)
|
|
472
474
|
if target is None:
|
|
473
475
|
return {ch: {"writes": []} for ch in channels}
|
|
@@ -475,23 +477,26 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
475
477
|
|
|
476
478
|
# Stage 1: paged K-JSONB-lookup scan, walking the parent chain in
|
|
477
479
|
# Python after each page. Stops as soon as every channel has its seed.
|
|
478
|
-
stage1_sql = _build_delta_stage1_sql(channels, paged=True)
|
|
480
|
+
stage1_sql = _build_delta_stage1_sql(channels, paged=True, include_cursor=True)
|
|
479
481
|
parent_of: dict[str, str | None] = {}
|
|
480
482
|
ver_by_i_by_cid: list[dict[str, str | None]] = [{} for _ in channels]
|
|
481
|
-
|
|
483
|
+
hb_by_i_by_cid: list[dict[str, bool]] = [{} for _ in channels]
|
|
484
|
+
inline_by_i_by_cid: list[dict[str, Any]] = [{} for _ in channels]
|
|
482
485
|
chain_by_ch: dict[str, list[str]] = {ch: [] for ch in channels}
|
|
483
486
|
seed_ver_by_ch: dict[str, str | None] = {ch: None for ch in channels}
|
|
487
|
+
seed_inline_by_ch: dict[str, Any] = {}
|
|
484
488
|
walk_cursor_by_ch: dict[str, str | None] = {}
|
|
485
489
|
seeded: set[str] = set()
|
|
486
|
-
cursor: str | None =
|
|
490
|
+
cursor: str | None = checkpoint_id
|
|
487
491
|
|
|
488
492
|
with self._cursor() as cur:
|
|
489
493
|
while True:
|
|
490
494
|
stage1_params: list[Any] = []
|
|
491
495
|
for ch in channels:
|
|
492
|
-
|
|
496
|
+
# ver_i, blob channel, blob version, inline_i
|
|
497
|
+
stage1_params.extend([ch, ch, ch, ch])
|
|
493
498
|
stage1_params.extend(
|
|
494
|
-
[thread_id, checkpoint_ns, cursor,
|
|
499
|
+
[thread_id, checkpoint_ns, cursor, _DELTA_PAGE_SIZE]
|
|
495
500
|
)
|
|
496
501
|
cur.execute(stage1_sql, stage1_params)
|
|
497
502
|
page = cur.fetchall()
|
|
@@ -502,16 +507,19 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
502
507
|
channels,
|
|
503
508
|
parent_of,
|
|
504
509
|
ver_by_i_by_cid,
|
|
505
|
-
|
|
510
|
+
hb_by_i_by_cid,
|
|
511
|
+
inline_by_i_by_cid,
|
|
506
512
|
)
|
|
507
513
|
self._try_advance_walks(
|
|
508
514
|
checkpoint_id,
|
|
509
515
|
channels,
|
|
510
516
|
parent_of,
|
|
511
517
|
ver_by_i_by_cid,
|
|
512
|
-
|
|
518
|
+
hb_by_i_by_cid,
|
|
519
|
+
inline_by_i_by_cid,
|
|
513
520
|
chain_by_ch,
|
|
514
521
|
seed_ver_by_ch,
|
|
522
|
+
seed_inline_by_ch,
|
|
515
523
|
walk_cursor_by_ch,
|
|
516
524
|
seeded,
|
|
517
525
|
)
|
|
@@ -520,6 +528,7 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
520
528
|
if len(seeded) == len(channels) or len(page) < _DELTA_PAGE_SIZE:
|
|
521
529
|
break
|
|
522
530
|
cursor = oldest
|
|
531
|
+
stage1_sql = _build_delta_stage1_sql(channels, paged=True)
|
|
523
532
|
|
|
524
533
|
# Stage 2: per-channel UNION ALL — one writes branch per channel
|
|
525
534
|
# with non-empty chain, plus one blob branch per seeded channel.
|
|
@@ -546,6 +555,7 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
546
555
|
channels=channels,
|
|
547
556
|
chain_by_ch=chain_by_ch,
|
|
548
557
|
seed_ver_by_ch=seed_ver_by_ch,
|
|
558
|
+
seed_inline_by_ch=seed_inline_by_ch,
|
|
549
559
|
stage2_rows=cast("list[_DeltaStage2Row]", stage2_rows),
|
|
550
560
|
)
|
|
551
561
|
|
|
@@ -417,29 +417,32 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
417
417
|
thread_id = config["configurable"]["thread_id"]
|
|
418
418
|
checkpoint_ns = config["configurable"].get("checkpoint_ns", "")
|
|
419
419
|
checkpoint_id = get_checkpoint_id(config)
|
|
420
|
-
if checkpoint_id
|
|
420
|
+
if not checkpoint_id:
|
|
421
421
|
target = await self.aget_tuple(config)
|
|
422
422
|
if target is None:
|
|
423
423
|
return {ch: {"writes": []} for ch in channels}
|
|
424
424
|
checkpoint_id = target.config["configurable"]["checkpoint_id"]
|
|
425
425
|
|
|
426
|
-
stage1_sql = _build_delta_stage1_sql(channels, paged=True)
|
|
426
|
+
stage1_sql = _build_delta_stage1_sql(channels, paged=True, include_cursor=True)
|
|
427
427
|
parent_of: dict[str, str | None] = {}
|
|
428
428
|
ver_by_i_by_cid: list[dict[str, str | None]] = [{} for _ in channels]
|
|
429
|
-
|
|
429
|
+
hb_by_i_by_cid: list[dict[str, bool]] = [{} for _ in channels]
|
|
430
|
+
inline_by_i_by_cid: list[dict[str, Any]] = [{} for _ in channels]
|
|
430
431
|
chain_by_ch: dict[str, list[str]] = {ch: [] for ch in channels}
|
|
431
432
|
seed_ver_by_ch: dict[str, str | None] = {ch: None for ch in channels}
|
|
433
|
+
seed_inline_by_ch: dict[str, Any] = {}
|
|
432
434
|
walk_cursor_by_ch: dict[str, str | None] = {}
|
|
433
435
|
seeded: set[str] = set()
|
|
434
|
-
cursor: str | None =
|
|
436
|
+
cursor: str | None = checkpoint_id
|
|
435
437
|
|
|
436
438
|
async with self._cursor() as cur:
|
|
437
439
|
while True:
|
|
438
440
|
stage1_params: list[Any] = []
|
|
439
441
|
for ch in channels:
|
|
440
|
-
|
|
442
|
+
# ver_i, blob channel, blob version, inline_i
|
|
443
|
+
stage1_params.extend([ch, ch, ch, ch])
|
|
441
444
|
stage1_params.extend(
|
|
442
|
-
[thread_id, checkpoint_ns, cursor,
|
|
445
|
+
[thread_id, checkpoint_ns, cursor, _DELTA_PAGE_SIZE]
|
|
443
446
|
)
|
|
444
447
|
await cur.execute(stage1_sql, stage1_params)
|
|
445
448
|
page = await cur.fetchall()
|
|
@@ -450,22 +453,26 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
450
453
|
channels,
|
|
451
454
|
parent_of,
|
|
452
455
|
ver_by_i_by_cid,
|
|
453
|
-
|
|
456
|
+
hb_by_i_by_cid,
|
|
457
|
+
inline_by_i_by_cid,
|
|
454
458
|
)
|
|
455
459
|
self._try_advance_walks(
|
|
456
460
|
checkpoint_id,
|
|
457
461
|
channels,
|
|
458
462
|
parent_of,
|
|
459
463
|
ver_by_i_by_cid,
|
|
460
|
-
|
|
464
|
+
hb_by_i_by_cid,
|
|
465
|
+
inline_by_i_by_cid,
|
|
461
466
|
chain_by_ch,
|
|
462
467
|
seed_ver_by_ch,
|
|
468
|
+
seed_inline_by_ch,
|
|
463
469
|
walk_cursor_by_ch,
|
|
464
470
|
seeded,
|
|
465
471
|
)
|
|
466
472
|
if len(seeded) == len(channels) or len(page) < _DELTA_PAGE_SIZE:
|
|
467
473
|
break
|
|
468
474
|
cursor = oldest
|
|
475
|
+
stage1_sql = _build_delta_stage1_sql(channels, paged=True)
|
|
469
476
|
|
|
470
477
|
channels_with_chain = [ch for ch in channels if chain_by_ch[ch]]
|
|
471
478
|
channels_with_seed = [ch for ch in channels if seed_ver_by_ch[ch] is not None]
|
|
@@ -490,6 +497,7 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
490
497
|
channels=channels,
|
|
491
498
|
chain_by_ch=chain_by_ch,
|
|
492
499
|
seed_ver_by_ch=seed_ver_by_ch,
|
|
500
|
+
seed_inline_by_ch=seed_inline_by_ch,
|
|
493
501
|
stage2_rows=cast("list[_DeltaStage2Row]", stage2_rows),
|
|
494
502
|
)
|
|
495
503
|
|
|
@@ -573,7 +581,7 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
573
581
|
while True:
|
|
574
582
|
try:
|
|
575
583
|
yield asyncio.run_coroutine_threadsafe(
|
|
576
|
-
anext(aiter_), # type: ignore[arg-type]
|
|
584
|
+
anext(aiter_), # type: ignore[arg-type]
|
|
577
585
|
self.loop,
|
|
578
586
|
).result()
|
|
579
587
|
except StopAsyncIteration:
|
|
@@ -680,5 +688,23 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
680
688
|
self.adelete_thread(thread_id), self.loop
|
|
681
689
|
).result()
|
|
682
690
|
|
|
691
|
+
def get_delta_channel_history(
|
|
692
|
+
self, *, config: RunnableConfig, channels: Sequence[str]
|
|
693
|
+
) -> Mapping[str, DeltaChannelHistory]:
|
|
694
|
+
"""Sync bridge to `aget_delta_channel_history`, guarded like `get_tuple`."""
|
|
695
|
+
try:
|
|
696
|
+
if asyncio.get_running_loop() is self.loop:
|
|
697
|
+
raise asyncio.InvalidStateError(
|
|
698
|
+
"Synchronous calls to AsyncPostgresSaver are only allowed from a "
|
|
699
|
+
"different thread. From the main thread, use the async interface. "
|
|
700
|
+
"For example, use `await checkpointer.aget_delta_channel_history(...)`."
|
|
701
|
+
)
|
|
702
|
+
except RuntimeError:
|
|
703
|
+
pass
|
|
704
|
+
return asyncio.run_coroutine_threadsafe(
|
|
705
|
+
self.aget_delta_channel_history(config=config, channels=channels),
|
|
706
|
+
self.loop,
|
|
707
|
+
).result()
|
|
708
|
+
|
|
683
709
|
|
|
684
710
|
__all__ = ["AsyncPostgresSaver", "AsyncShallowPostgresSaver", "Conn"]
|