SyncStore or AsyncStore from contree_sdk.store, implement its methods,
and pass an instance through store=. The session uses the same interface to save
history and resume work, regardless of the storage backend.
Start with Save and resume a session for memory and SQLite examples. This page covers
extension points and the guarantees a custom implementation must preserve.
Extend an existing implementation
If you only need different defaults, subclass a supplied Store. This example gives newly created trees a seven-day lifetime unless the caller supplies a TTL. SQLite still handles persistence, atomic writes, and pagination. The program saves a file, closes the Store, and opens the same session through a new Store instance. It printssaved. Configure a connection as described in
Connection sources.
- Sync
- Async
await. The supplied Store stays open after the session context exits.
The outer Store context closes it.
Reopening a tree does not renew its expiry. Use set_session_ttl() to change an
existing tree’s lifetime. Expiry makes its history unavailable; it does not delete
server images or stop running operations. The example changes the default for
tree creation only. Other methods retain the supplied SQLite behavior.
Implement storage in another database
For a different backend, inheritSyncStore or AsyncStore directly. Implement
every abstract method below with your database client. PostgreSQL and Redis are
possible application backends; the SDK does not include implementations for them.
The async interface has the same methods and results, with
async def and
await. Use an async database client or explicitly offload blocking I/O. The base
classes supply the matching context-manager methods through close().
Store preserves Node.id, parent_id, kind, and JSON-object data. A tree also
has a kind: sessions, builds, and upload reuse can share a backend. Your Store
must preserve their data without interpreting session commands or Docker hashes.
Use Tree stores for exact signatures, limits, and error behavior.
Preserve the storage guarantees
- Make each call atomic across all clients, including separate processes and database connections. A lock in one Python object is insufficient.
- Require a live tree and an existing parent in that tree for
append(). Allow only one root. A late append must not recreate a deleted or expired tree. - Accept an identical repeated node without duplication. Raise
NodeConflictErrorif the same identity has different contents or a second root is inserted. Do not overwrite saved nodes. - Return independent JSON values. Changes to a caller’s dictionary must not
change stored data. Preserve atomic batch reads in
get_nodes(). - Apply filters before pagination. Order identity-based lists by ID and history by ancestry. Return opaque continuation cursors; pages need not share a snapshot.
- Apply TTL to the whole tree. Reads and appends must not extend its lifetime.
Define the backend policy for
ttl=Noneand preserve the contract’s expiry errors.
store= to sessions
or helpers, and close it after all users finish.