# Class LittleGhost::SessionStores::Filesystem

Documentation version: Edge

Canonical HTML: https://littleghostai.org/docs/LittleGhost/SessionStores/Filesystem.html

Filesystem preserves LittleGhost sessions across process restarts in an
application-controlled directory. Use it for durable local development, a
single-host service, or processes that share a suitable filesystem.

    store = LittleGhost::SessionStores::Filesystem.new(
      root: "/var/lib/customer_support/sessions"
    )

Configure the resulting store through Configuration#session_store, or pass it
directly when opening a Session. Calls for the same session wait for one
writer, including when separate Ruby processes share the root.

> <strong>Safety note:</strong> The root contains readable session data and is
  not encrypted. Its complete path must be application-controlled: anyone able
  to read it can read session data, and anyone able to replace it can alter
  sessions.

> Session data is stored as ordinary JSON with canonical String keys. A value
that cannot be represented that way raises ProtocolError without replacing the
previous snapshot. Shared roots require filesystem support for file locking
and atomic rename. Waiting for another process does not pause other scheduled
fibers. In a scheduled fiber, file transactions use LittleGhost's shared
thread pool. Set Configuration#blocking_pool_capacity during process startup
if measurements show calls waiting for its two default workers. Store calls do
not accept cancellation or deadlines, so a cross-process lock wait continues
until the other process releases it.

## Inheritance

`LittleGhost::SessionStores::Filesystem < LittleGhost::SessionStore`

## Class methods

<a id="method-c-new"></a>
### `.new`

```ruby
.new(root:)
```

Creates a store rooted at `root` and creates the directory when needed.

`root` must be a private, non-symlinked directory. The application owns the
complete path and must not let an untrusted request choose it. Raises
ArgumentError when the root does not meet those requirements.

## Instance methods

<a id="method-i-append"></a>
### `#append`

```ruby
#append(id, messages:, state:, metadata:, expected_count:, actor_id: nil)
```

Atomically appends sanitized `messages` and returns the updated snapshot.

`expected_count` must match the stored history length. `state` and `metadata`
must contain values this store can represent as JSON. Raises ProtocolError
when another writer changed the session or the snapshot cannot be read or
written. Raises Error when `actor_id` does not match the session.

<a id="method-i-load"></a>
### `#load`

```ruby
#load(id, actor_id: nil)
```

Returns the stored snapshot for `id`, or `nil` before the first write.

`actor_id` must match the actor that created an existing session. Raises Error
for an actor mismatch and ProtocolError for an invalid or unsafe persisted
snapshot.

<a id="method-i-replace"></a>
### `#replace`

```ruby
#replace(id, messages:, state:, metadata:, actor_id: nil)
```

Atomically replaces the complete persisted snapshot and returns it.

`state`, `metadata`, and `actor_id` follow the same requirements as #append.
