# `Slap.SlateDB.Reader`
[🔗](https://github.com/mjrusso/slap/blob/slap_slatedb-v0.2.0/slap_slatedb/lib/slap/slatedb/reader.ex#L1)

Read-only access to a database, alongside its writer.

A reader does not fence the writer, so any number of readers can follow one
database, in this VM or elsewhere. It picks up the writer's changes by
polling the manifest and replaying the WAL.

    {:ok, reader} = Slap.SlateDB.Reader.open("my-db", store: store)
    {:ok, value} = Slap.SlateDB.Reader.get(reader, "key")
    reader |> Slap.SlateDB.Reader.scan(prefix: "user:") |> Enum.take(10)
    :ok = Slap.SlateDB.Reader.close(reader)

A reader sees writes once they are durable (in the WAL in object storage),
within `manifest_poll_interval`. It does not see writes that are still only
in the writer's memory.

# `t`

```elixir
@opaque t()
```

# `close`

```elixir
@spec close(t(), keyword()) :: :ok | {:error, Slap.SlateDB.Error.t()}
```

Closes the reader. It waits for calls in flight; later calls get a
`:closed` error. Closing twice is allowed. A `:managed` reader's
checkpoint is left to expire.

# `durable_seq`

```elixir
@spec durable_seq(t()) :: non_neg_integer()
```

Returns the highest durable sequence number the reader has seen.

# `get`

```elixir
@spec get(t(), binary(), keyword()) ::
  {:ok, binary() | nil} | {:error, Slap.SlateDB.Error.t()}
```

Reads `key`. Takes the options of `Slap.SlateDB.get/3`.

# `get_key_value`

```elixir
@spec get_key_value(t(), binary(), keyword()) ::
  {:ok, Slap.SlateDB.key_value() | nil} | {:error, Slap.SlateDB.Error.t()}
```

Reads `key` with its metadata, like `Slap.SlateDB.get_key_value/3`.

# `iterator`

```elixir
@spec iterator(t(), keyword()) ::
  {:ok, Slap.SlateDB.Iterator.t()} | {:error, Slap.SlateDB.Error.t()}
```

Opens a `Slap.SlateDB.Iterator`. Takes the options of `Slap.SlateDB.iterator/2`.

# `open`

```elixir
@spec open(String.t(), keyword()) :: {:ok, t()} | {:error, Slap.SlateDB.Error.t()}
```

Opens a reader for the database at `path`.

## Options

  * `:store` - required, as for `Slap.SlateDB.open/2`.
  * `:mode` - how the reader tracks the database:
    * `:managed` (default) - the reader keeps its own checkpoint, refreshed
      as it follows the writer, so garbage collection cannot delete files
      it is reading.
    * `:latest` - no checkpoint and no writes to the store. Reads can fail
      if garbage collection deletes a file the reader still uses.
  * `:checkpoint` - a checkpoint id (from `Slap.SlateDB.create_checkpoint/2`).
    The reader stays at that checkpoint instead of following the writer.
  * `:settings` - a map of reader options, merged over SlateDB's
    defaults: `manifest_poll_interval` (default 10 s),
    `checkpoint_lifetime` (10 min), `max_memtable_bytes`,
    `skip_wal_replay`, `object_store_cache_options` and so on. Give the two
    durations in milliseconds or as a string such as `"100ms"`, `"10s"`,
    `"5m"` or `"1h"`.
  * `:cache` - as for `Slap.SlateDB.open/2`.
  * `:merge_operator` - the database's merge operator, if it has one.
  * `:timeout` - see `Slap.SlateDB`.

# `scan`

```elixir
@spec scan(t(), keyword()) :: Enumerable.t()
```

Scans rows. Takes the options of `Slap.SlateDB.scan/2`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
