langgraph-checkpoint-sqlite 1.0.1__tar.gz → 1.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_sqlite-1.0.1 → langgraph_checkpoint_sqlite-1.0.3}/PKG-INFO +2 -2
- {langgraph_checkpoint_sqlite-1.0.1 → langgraph_checkpoint_sqlite-1.0.3}/langgraph/checkpoint/sqlite/__init__.py +17 -14
- {langgraph_checkpoint_sqlite-1.0.1 → langgraph_checkpoint_sqlite-1.0.3}/langgraph/checkpoint/sqlite/aio.py +66 -30
- {langgraph_checkpoint_sqlite-1.0.1 → langgraph_checkpoint_sqlite-1.0.3}/pyproject.toml +2 -2
- {langgraph_checkpoint_sqlite-1.0.1 → langgraph_checkpoint_sqlite-1.0.3}/README.md +0 -0
- {langgraph_checkpoint_sqlite-1.0.1 → langgraph_checkpoint_sqlite-1.0.3}/langgraph/checkpoint/py.typed +0 -0
- {langgraph_checkpoint_sqlite-1.0.1 → langgraph_checkpoint_sqlite-1.0.3}/langgraph/checkpoint/sqlite/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: langgraph-checkpoint-sqlite
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: Library with a SQLite implementation of LangGraph checkpoint saver.
|
|
5
5
|
Home-page: https://www.github.com/langchain-ai/langgraph
|
|
6
6
|
License: MIT
|
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
14
|
Requires-Dist: aiosqlite (>=0.20.0,<0.21.0)
|
|
15
|
-
Requires-Dist: langgraph-checkpoint (>=1.0.
|
|
15
|
+
Requires-Dist: langgraph-checkpoint (>=1.0.8,<2.0.0)
|
|
16
16
|
Project-URL: Repository, https://www.github.com/langchain-ai/langgraph
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
|
|
@@ -104,10 +104,12 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
104
104
|
with SqliteSaver.from_conn_string("checkpoints.sqlite") as memory:
|
|
105
105
|
...
|
|
106
106
|
"""
|
|
107
|
-
with
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
with closing(
|
|
108
|
+
sqlite3.connect(
|
|
109
|
+
conn_string,
|
|
110
|
+
# https://ricardoanderegg.com/posts/python-sqlite-thread-safety/
|
|
111
|
+
check_same_thread=False,
|
|
112
|
+
)
|
|
111
113
|
) as conn:
|
|
112
114
|
yield SqliteSaver(conn)
|
|
113
115
|
|
|
@@ -163,14 +165,15 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
163
165
|
Yields:
|
|
164
166
|
sqlite3.Cursor: A cursor for the SQLite database.
|
|
165
167
|
"""
|
|
166
|
-
self.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
168
|
+
with self.lock:
|
|
169
|
+
self.setup()
|
|
170
|
+
cur = self.conn.cursor()
|
|
171
|
+
try:
|
|
172
|
+
yield cur
|
|
173
|
+
finally:
|
|
174
|
+
if transaction:
|
|
175
|
+
self.conn.commit()
|
|
176
|
+
cur.close()
|
|
174
177
|
|
|
175
178
|
def get_tuple(self, config: RunnableConfig) -> Optional[CheckpointTuple]:
|
|
176
179
|
"""Get a checkpoint tuple from the database.
|
|
@@ -396,7 +399,7 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
396
399
|
checkpoint_ns = config["configurable"]["checkpoint_ns"]
|
|
397
400
|
type_, serialized_checkpoint = self.serde.dumps_typed(checkpoint)
|
|
398
401
|
serialized_metadata = self.jsonplus_serde.dumps(metadata)
|
|
399
|
-
with self.
|
|
402
|
+
with self.cursor() as cur:
|
|
400
403
|
cur.execute(
|
|
401
404
|
"INSERT OR REPLACE INTO checkpoints (thread_id, checkpoint_ns, checkpoint_id, parent_checkpoint_id, type, checkpoint, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
402
405
|
(
|
|
@@ -432,7 +435,7 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
432
435
|
writes (Sequence[Tuple[str, Any]]): List of writes to store, each as (channel, value) pair.
|
|
433
436
|
task_id (str): Identifier for the task creating the writes.
|
|
434
437
|
"""
|
|
435
|
-
with self.
|
|
438
|
+
with self.cursor() as cur:
|
|
436
439
|
cur.executemany(
|
|
437
440
|
"INSERT OR IGNORE INTO writes (thread_id, checkpoint_ns, checkpoint_id, task_id, idx, channel, type, value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
|
438
441
|
[
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import functools
|
|
3
2
|
from contextlib import asynccontextmanager
|
|
4
3
|
from typing import (
|
|
5
4
|
Any,
|
|
6
5
|
AsyncIterator,
|
|
7
6
|
Dict,
|
|
8
7
|
Iterator,
|
|
8
|
+
List,
|
|
9
9
|
Optional,
|
|
10
10
|
Sequence,
|
|
11
11
|
Tuple,
|
|
@@ -31,20 +31,6 @@ from langgraph.checkpoint.sqlite.utils import search_where
|
|
|
31
31
|
T = TypeVar("T", bound=callable)
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
def not_implemented_sync_method(func: T) -> T:
|
|
35
|
-
@functools.wraps(func)
|
|
36
|
-
def wrapper(*args, **kwargs):
|
|
37
|
-
raise NotImplementedError(
|
|
38
|
-
"The AsyncSqliteSaver does not support synchronous methods. "
|
|
39
|
-
"Consider using the SqliteSaver instead.\n"
|
|
40
|
-
"from langgraph.checkpoint.sqlite import SqliteSaver\n"
|
|
41
|
-
"See https://langchain-ai.github.io/langgraph/reference/checkpoints/langgraph.checkpoint.sqlite.SqliteSaver "
|
|
42
|
-
"for more information."
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
return wrapper
|
|
46
|
-
|
|
47
|
-
|
|
48
34
|
class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
49
35
|
"""An asynchronous checkpoint saver that stores checkpoints in a SQLite database.
|
|
50
36
|
|
|
@@ -132,6 +118,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
132
118
|
self.jsonplus_serde = JsonPlusSerializer()
|
|
133
119
|
self.conn = conn
|
|
134
120
|
self.lock = asyncio.Lock()
|
|
121
|
+
self.loop = asyncio.get_running_loop()
|
|
135
122
|
self.is_setup = False
|
|
136
123
|
|
|
137
124
|
@classmethod
|
|
@@ -150,16 +137,24 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
150
137
|
async with aiosqlite.connect(conn_string) as conn:
|
|
151
138
|
yield AsyncSqliteSaver(conn)
|
|
152
139
|
|
|
153
|
-
@not_implemented_sync_method
|
|
154
140
|
def get_tuple(self, config: RunnableConfig) -> Optional[CheckpointTuple]:
|
|
155
141
|
"""Get a checkpoint tuple from the database.
|
|
156
142
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
143
|
+
This method retrieves a checkpoint tuple from the SQLite database based on the
|
|
144
|
+
provided config. If the config contains a "checkpoint_id" key, the checkpoint with
|
|
145
|
+
the matching thread ID and checkpoint ID is retrieved. Otherwise, the latest checkpoint
|
|
146
|
+
for the given thread ID is retrieved.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
config (RunnableConfig): The config to use for retrieving the checkpoint.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Optional[CheckpointTuple]: The retrieved checkpoint tuple, or None if no matching checkpoint was found.
|
|
160
153
|
"""
|
|
154
|
+
return asyncio.run_coroutine_threadsafe(
|
|
155
|
+
self.aget_tuple(config), self.loop
|
|
156
|
+
).result()
|
|
161
157
|
|
|
162
|
-
@not_implemented_sync_method
|
|
163
158
|
def list(
|
|
164
159
|
self,
|
|
165
160
|
config: Optional[RunnableConfig],
|
|
@@ -168,21 +163,60 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
168
163
|
before: Optional[RunnableConfig] = None,
|
|
169
164
|
limit: Optional[int] = None,
|
|
170
165
|
) -> Iterator[CheckpointTuple]:
|
|
171
|
-
"""List checkpoints from the database.
|
|
166
|
+
"""List checkpoints from the database asynchronously.
|
|
167
|
+
|
|
168
|
+
This method retrieves a list of checkpoint tuples from the SQLite database based
|
|
169
|
+
on the provided config. The checkpoints are ordered by checkpoint ID in descending order (newest first).
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
config (Optional[RunnableConfig]): Base configuration for filtering checkpoints.
|
|
173
|
+
filter (Optional[Dict[str, Any]]): Additional filtering criteria for metadata.
|
|
174
|
+
before (Optional[RunnableConfig]): If provided, only checkpoints before the specified checkpoint ID are returned. Defaults to None.
|
|
175
|
+
limit (Optional[int]): Maximum number of checkpoints to return.
|
|
172
176
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
Or consider using the [SqliteSaver][sqlitesaver] checkpointer.
|
|
177
|
+
Yields:
|
|
178
|
+
Iterator[CheckpointTuple]: An iterator of matching checkpoint tuples.
|
|
176
179
|
"""
|
|
180
|
+
aiter_ = self.alist(config, filter=filter, before=before, limit=limit)
|
|
181
|
+
while True:
|
|
182
|
+
try:
|
|
183
|
+
yield asyncio.run_coroutine_threadsafe(
|
|
184
|
+
anext(aiter_), self.loop
|
|
185
|
+
).result()
|
|
186
|
+
except StopAsyncIteration:
|
|
187
|
+
break
|
|
177
188
|
|
|
178
|
-
@not_implemented_sync_method
|
|
179
189
|
def put(
|
|
180
190
|
self,
|
|
181
191
|
config: RunnableConfig,
|
|
182
192
|
checkpoint: Checkpoint,
|
|
183
193
|
metadata: CheckpointMetadata,
|
|
194
|
+
new_versions: ChannelVersions,
|
|
184
195
|
) -> RunnableConfig:
|
|
185
|
-
"""Save a checkpoint to the database.
|
|
196
|
+
"""Save a checkpoint to the database.
|
|
197
|
+
|
|
198
|
+
This method saves a checkpoint to the SQLite database. The checkpoint is associated
|
|
199
|
+
with the provided config and its parent config (if any).
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
config (RunnableConfig): The config to associate with the checkpoint.
|
|
203
|
+
checkpoint (Checkpoint): The checkpoint to save.
|
|
204
|
+
metadata (CheckpointMetadata): Additional metadata to save with the checkpoint.
|
|
205
|
+
new_versions (ChannelVersions): New channel versions as of this write.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
RunnableConfig: Updated configuration after storing the checkpoint.
|
|
209
|
+
"""
|
|
210
|
+
return asyncio.run_coroutine_threadsafe(
|
|
211
|
+
self.aput(config, checkpoint, metadata, new_versions), self.loop
|
|
212
|
+
).result()
|
|
213
|
+
|
|
214
|
+
def put_writes(
|
|
215
|
+
self, config: RunnableConfig, writes: List[Tuple[str, Any]], task_id: str
|
|
216
|
+
) -> None:
|
|
217
|
+
return asyncio.run_coroutine_threadsafe(
|
|
218
|
+
self.aput_writes(config, writes, task_id), self.loop
|
|
219
|
+
).result()
|
|
186
220
|
|
|
187
221
|
async def setup(self) -> None:
|
|
188
222
|
"""Set up the checkpoint database asynchronously.
|
|
@@ -242,7 +276,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
242
276
|
"""
|
|
243
277
|
await self.setup()
|
|
244
278
|
checkpoint_ns = config["configurable"].get("checkpoint_ns", "")
|
|
245
|
-
async with self.conn.cursor() as cur:
|
|
279
|
+
async with self.lock, self.conn.cursor() as cur:
|
|
246
280
|
# find the latest checkpoint for the thread_id
|
|
247
281
|
if checkpoint_id := get_checkpoint_id(config):
|
|
248
282
|
await cur.execute(
|
|
@@ -337,7 +371,9 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
337
371
|
ORDER BY checkpoint_id DESC"""
|
|
338
372
|
if limit:
|
|
339
373
|
query += f" LIMIT {limit}"
|
|
340
|
-
async with self.
|
|
374
|
+
async with self.lock, self.conn.execute(
|
|
375
|
+
query, params
|
|
376
|
+
) as cur, self.conn.cursor() as wcur:
|
|
341
377
|
async for (
|
|
342
378
|
thread_id,
|
|
343
379
|
checkpoint_ns,
|
|
@@ -404,7 +440,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
404
440
|
checkpoint_ns = config["configurable"]["checkpoint_ns"]
|
|
405
441
|
type_, serialized_checkpoint = self.serde.dumps_typed(checkpoint)
|
|
406
442
|
serialized_metadata = self.jsonplus_serde.dumps(metadata)
|
|
407
|
-
async with self.conn.execute(
|
|
443
|
+
async with self.lock, self.conn.execute(
|
|
408
444
|
"INSERT OR REPLACE INTO checkpoints (thread_id, checkpoint_ns, checkpoint_id, parent_checkpoint_id, type, checkpoint, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
409
445
|
(
|
|
410
446
|
str(config["configurable"]["thread_id"]),
|
|
@@ -441,7 +477,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
441
477
|
task_id (str): Identifier for the task creating the writes.
|
|
442
478
|
"""
|
|
443
479
|
await self.setup()
|
|
444
|
-
async with self.conn.cursor() as cur:
|
|
480
|
+
async with self.lock, self.conn.cursor() as cur:
|
|
445
481
|
await cur.executemany(
|
|
446
482
|
"INSERT OR IGNORE INTO writes (thread_id, checkpoint_ns, checkpoint_id, task_id, idx, channel, type, value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
|
447
483
|
[
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "langgraph-checkpoint-sqlite"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.3"
|
|
4
4
|
description = "Library with a SQLite 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"
|
|
13
|
-
langgraph-checkpoint = "^1.0.
|
|
13
|
+
langgraph-checkpoint = "^1.0.8"
|
|
14
14
|
aiosqlite = "^0.20.0"
|
|
15
15
|
|
|
16
16
|
[tool.poetry.group.dev.dependencies]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|