org.llm4s.agent.graph.sqlite

Members list

Type members

Classlikes

final class SqliteCheckpointer extends Checkpointer, AutoCloseable

A durable org.llm4s.agent.graph.Checkpointer in one SQLite database file: threads, their checkpoint histories, pending writes, event logs and run claims survive a restart, and several runtimes - in this process or in others on the same host - can share the file, each through a store of its own.

A durable org.llm4s.agent.graph.Checkpointer in one SQLite database file: threads, their checkpoint histories, pending writes, event logs and run claims survive a restart, and several runtimes - in this process or in others on the same host - can share the file, each through a store of its own.

Open it with SqliteCheckpointer.open and close it with close. It meets the Checkpointer contract (and passes CheckpointerContract from llm4s-agent-testkit):

  • '''Atomic, fenced commits.''' Every call that writes is one BEGIN IMMEDIATE transaction: a Commit's checkpoint, pending writes and events land together or not at all, and the claim's token and the thread's version are checked inside the same transaction, so two stores over one file cannot both pass the checks.
  • '''Claims expire by clock''', the clock this store was opened with: the clock of the process that grants or renews a claim decides when it lapses. Stores in processes on different hosts sharing one file therefore judge expiry by different clocks, and skew between them changes a claim's effective ttl (see docs/guide/agents/durable-checkpointers.md); fencing keeps writes safe regardless.
  • '''History and retention.''' Every checkpoint a commit supersedes stays in the file, readable with history (newest first, paged through the (thread, position) primary key) and checkpoint, until prune, a commit's retractTurn or deleteThread removes it; each of those is one write transaction too.
  • '''Fencing tokens''' come from one counter for the whole file, stored in it, so they keep increasing across restarts and deleteThread, and are never issued twice.
  • '''Data only.''' Checkpoints, pending writes and events are stored as JSON - the checkpoint through Checkpoint.toJson, which records its format version - and decoded on read, so nothing executable is stored.
  • '''Change notification by polling.''' SQLite cannot tell a connection that another has committed, so this store keeps Checkpointer.awaitEventsAfter's default: a subscription watching it reads the event log once per WatchPolicy.pollInterval, and sees commits made through other stores on the file that long after they land.

The database runs in WAL mode with synchronous = FULL: readers never block the writer, and a commit that returned survives a crash or a power loss. SQLite admits one writer at a time per file; a write that finds another connection writing waits up to SqliteCheckpointerConfig.busyTimeout, then fails with a ProcessingError, changing nothing. WAL needs shared memory between the processes that open the file, so keep the file on a local disk - not on a network file system.

One store is one connection, and its calls are serialised: it is safe to call from any number of threads. Every failure of the database itself is a ProcessingError, and so is any call after close.

Attributes

Companion
object
Supertypes
trait AutoCloseable
trait Checkpointer
class Object
trait Matchable
class Any

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
final case class SqliteCheckpointerConfig

How a SqliteCheckpointer uses its database connection.

How a SqliteCheckpointer uses its database connection.

busyTimeout is how long a write waits for the database's write lock while another connection - another store over the same file, in this process or another - holds it, before the call fails. SQLite allows one writer at a time per file, and every write here is short (one transaction per call), so a wait is brief; a call that still times out returns a ProcessingError and changes nothing. It is rounded up to whole milliseconds, and must be positive and at most Int.MaxValue milliseconds: apply and the with* setters throw IllegalArgumentException otherwise, and SqliteCheckpointerConfig.of returns a ValidationError.

The journal mode and sync level are not configurable: the store always runs in WAL mode with synchronous = FULL, so readers never block the writer and a commit that returned survives a power loss.

Attributes

Companion
object
Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all

Attributes

Companion
class
Supertypes
trait Product
trait Mirror
class Object
trait Matchable
class Any
Self type