Class FileSessionStore<S>

java.lang.Object
com.google.genkit.ai.agent.FileSessionStore<S>
Type Parameters:
S - the type of custom session state
All Implemented Interfaces:
SessionStore<S>, SnapshotReader<S>, SnapshotSubscriber, SnapshotWriter<S>

public final class FileSessionStore<S> extends Object implements SessionStore<S>, SnapshotSubscriber
Disk-backed implementation of SessionStore and SnapshotSubscriber.

On-disk layout

 <dir>/<prefix>/<snapshotId>.json              one snapshot per file
 <dir>/<prefix>/.pointers/<sessionId>.json     pointer: { currentSnapshotId, currentCreatedAt, updatedAt }
 

The default prefix is "global".

Atomic writes

Each write goes to a .tmp file first, then is renamed to the target path using StandardCopyOption.ATOMIC_MOVE (falling back to StandardCopyOption.REPLACE_EXISTING if the filesystem does not support atomic moves). This ensures no partial JSON files are visible.

Subscriber / polling

Subscriptions use polling (a shared daemon ScheduledExecutorService) rather than WatchService. This is simpler and more reliable across platforms (particularly macOS where WatchService uses polling internally anyway). The poll interval defaults to 2000 ms and can be overridden via the builder for fast-iteration tests.

De-duplication is done by comparing the serialised content of the snapshot file on each poll tick; the callback fires only when the content has changed.

  • Constructor Details

    • FileSessionStore

      public FileSessionStore(String dir)
      Creates a new FileSessionStore with default options (prefix = "global", no chain pruning, polling every 2000 ms).
      Parameters:
      dir - the root directory for persisted snapshots; created if absent
  • Method Details

    • builder

      public static <S> FileSessionStore.Builder<S> builder(String dir)
      Creates a builder for FileSessionStore.
      Type Parameters:
      S - the type of custom session state
      Parameters:
      dir - the root directory for persisted snapshots
      Returns:
      a new builder
    • getSnapshot

      public SessionSnapshot<S> getSnapshot(GetSnapshotOptions opts)
      Retrieves a session snapshot.

      When GetSnapshotOptions.getSnapshotId() is set the store returns that specific snapshot. When GetSnapshotOptions.getSessionId() is set the store resolves and returns the latest leaf snapshot for that session. Returns null if no matching snapshot exists.

      When GetSnapshotOptions.getSnapshotId() is set, reads <prefix>/<id>.json and deserialises it (or returns null if absent). When GetSnapshotOptions.getSessionId() is set, tries the pointer first; falls back to scanning all *.json files in the prefix dir (skipping .pointers/), runs LeafSelection, rewrites the pointer, and returns the leaf.

      Specified by:
      getSnapshot in interface SnapshotReader<S>
      Parameters:
      opts - options specifying which snapshot to retrieve; exactly one of snapshotId/sessionId must be set
      Returns:
      the matching snapshot, or null if none exists
    • saveSnapshot

      public String saveSnapshot(String snapshotId, SnapshotMutator<S> mutator, SessionStoreOptions options)
      Atomically reads the snapshot identified by snapshotId (or creates a new one), applies mutator, and persists the result.

      Implements the full saveSnapshot contract (mirrors InMemorySessionStore), but persists to disk:

      1. Validate path safety for snapshotId (if non-null).
      2. Under lock: read existing snapshot file.
      3. Apply mutator; if result is null, return null (no write).
      4. Determine final id; apply sessionId / status defaulting.
      5. Atomic write to <prefix>/<finalId>.json.
      6. Advance pointer if this is a new snapshot row.
      7. Prune chain if maxPersistedChainLength > 0.
      8. Notify subscribers if status changed.
      Specified by:
      saveSnapshot in interface SnapshotWriter<S>
      Parameters:
      snapshotId - the ID of the snapshot to write; if null the store mints a UUID
      mutator - the pure read-modify-write function; receives the existing snapshot (or null) and returns the snapshot to persist, or null to decline
      options - store options
      Returns:
      the snapshot ID that was written, or null if the mutator declined
    • onSnapshotStateChange

      public AutoCloseable onSnapshotStateChange(String snapshotId, Consumer<SessionSnapshot<?>> cb, SessionStoreOptions options)
      Subscribes to status changes for the snapshot identified by snapshotId.

      Invokes cb immediately with the current snapshot and again on every subsequent change. The returned AutoCloseable unsubscribes when closed.

      Registers a polling subscription for the snapshot identified by snapshotId. If the snapshot file already exists, the callback is fired immediately with the current content. A shared daemon ScheduledExecutorService polls the file every snapshotWatchPollIntervalMs milliseconds; the callback fires when the serialised content changes. Calling AutoCloseable.close() on the returned handle cancels the poll.

      Specified by:
      onSnapshotStateChange in interface SnapshotSubscriber
      Parameters:
      snapshotId - the snapshot to observe
      cb - callback invoked with the updated snapshot on each change
      options - store options
      Returns:
      a handle that cancels the subscription when AutoCloseable.close() is called