Skip to main content
Use your own Store when session history must live in your database or service. Inherit 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 prints saved. Configure a connection as described in Connection sources.
Run the async example inside an async function or a notebook that supports top-level 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, inherit SyncStore 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 NodeConflictError if 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=None and preserve the contract’s expiry errors.
Test retries, conflicting inserts, pagination, expiry, and deletion through separate connections before using a new backend. Also test saving a session and resuming it through a new Store instance. The Store contract defines the complete requirements. Store saves history and references to remote images. Session controls execution, the selected node, and local branch names. A custom Store does not need to run commands or choose a shared current position. Pass it through store= to sessions or helpers, and close it after all users finish.