Directory where snapshot JSON files are stored.
Optionaloptions: {OptionalmaxPersistedChainLength?: numberWhen set, snapshots older than this many entries in a chain are automatically deleted on each save.
OptionalrejectBranchingSessions?: booleanWhen true, a sessionId lookup
that resolves to a branched history (more than one leaf) throws
FAILED_PRECONDITION instead of returning the latest leaf. Defaults to
false; opt in (e.g. in dev) to surface accidental branching early.
OptionalsnapshotPathPrefix?: (options?: SessionStoreOptions) => stringReturns a sub-directory prefix derived
from the call's SessionStoreOptions (e.g. the authenticated user
id from options.context), useful for multi-tenant isolation: all reads
and writes are scoped to that prefix, so one tenant can never see
another's snapshots. Defaults to "global".
OptionalsnapshotWatchPollIntervalMs?: numberPolling interval (ms) for the
FileSessionStore.onSnapshotStateChange fallback that backstops
fs.watch (which can miss events on some filesystems, e.g. network
mounts). Defaults to DEFAULT_SNAPSHOT_WATCH_POLL_INTERVAL_MS.
Loads a snapshot either by its snapshotId or by sessionId.
See GetSnapshotOptions for the lookup semantics (exactly one of
snapshotId / sessionId; sessionId resolves to the session's latest
leaf snapshot, optionally rejecting branching histories).
Watches a single snapshot file for changes and invokes callback with the
parsed snapshot whenever it changes.
Unlike InMemorySessionStore, file-backed snapshots are frequently
mutated by a different process (e.g. the request handler that received an
abort writes status: 'aborted', while a detached background worker is the
one watching). Detecting that requires observing the filesystem rather than
in-process saveSnapshot calls.
Reliability comes from two layers:
fs.watch on the (per-tenant) prefix directory, filtered to the target
<snapshotId>.json. This is low latency but can miss events on some
filesystems (network mounts, certain container volumes).snapshotWatchPollIntervalMs) that re-reads the file
on an interval, backstopping any events fs.watch drops. Its timer is
unref'd so it never keeps the process alive on its own.Callbacks are de-duplicated by serialized content, so the noisy/duplicate
events fs.watch emits collapse into one callback per real change.
Transient read errors (e.g. a partially written file mid-rewrite, or a
not-yet-created file) are swallowed; the next event/poll re-reads.
Optionaloptions: SessionStoreOptionsAn unsubscribe function that stops watching and polling.
Atomically reads the current snapshot (if snapshotId is provided),
passes it to mutator, and persists the result.
snapshotId is provided the store reads the existing snapshot
and passes it to the mutator. The mutator can inspect the current
state (e.g. to check for concurrent status changes) and return the
updated snapshot to save, or null to skip the write.snapshotId is undefined the store passes undefined to
the mutator (signaling a new snapshot). The store assigns a new
identifier.Implementations should ensure the read→mutate→write cycle is atomic to prevent race conditions (e.g. a "done" write overwriting a concurrent "aborted" status).
The mutator can:
null to silently skip the write.Optionaloptions: SessionStoreOptionsThe snapshotId that was used, or null when the mutator
returned null.
A Node.js file-system backed session snapshot store.
Snapshots are stored as flat JSON files keyed by their
snapshotId, under an optional per-tenant sub-directoryprefix:File layout:
dirPath/<prefix>/<snapshotId>.jsongetSnapshot({ sessionId })resolves the session's current leaf via a tiny per-session pointer file (<prefix>/.pointers/<sessionId>.json, see PointerDoc) - one pointer read plus one snapshot read. When the pointer is missing (e.g. a legacy store) or stale it transparently falls back to scanning the prefix directory and selecting the single leaf whosesessionIdmatches, then rewrites the pointer so subsequent lookups are fast again.