# `Replicant.Snapshotter`
[🔗](https://github.com/baselabs/replicant/blob/v0.3.1/lib/replicant/snapshotter.ex#L1)

Reads a consistent snapshot of the publication's tables (spec §4) on its own normal
Postgrex connection, at the LSN a durable slot exported via `EXPORT_SNAPSHOT`, and
pushes the rows to the sink as `%Change{op: :snapshot}` batches — then durably sets the
sink checkpoint to the snapshot's consistent point (the handoff commit). Spawned and
LINKED to `Replicant.Connection`, which holds the exported snapshot valid by staying
idle (proven safe past `wal_sender_timeout`, spec §11). The link binds the snapshotter's
lifetime to the pipeline: a Connection/pipeline teardown mid-snapshot tears the
snapshotter down with it, so an orphan can never mutate the sink after the pipeline is
gone. Graceful completion exits `:normal` (which never propagates over the link), so the
`{:snapshot_done, lsn}` / `{:snapshot_failed, err}` messages still drive the handoff.

## Value-free boundary (Critical Rule 1)
A Postgrex query/cursor fault — raised OR returned — can embed row/column values in its
message. Every fault is scrubbed to a value-free `%Replicant.Error{reason:
:snapshot_failed}` (only a structural module name kept) before the Connection is told.
On success it sends `{:snapshot_done, consistent_point}`; on any fault
`{:snapshot_failed, %Error{}}`. It reads on a SEPARATE connection, so it never blocks
the Connection's keepalive path.

## Source-side cost
The consistent-snapshot read holds a single long-running `REPEATABLE READ` transaction
open for the whole backfill (a slow sink extends it), which pins `xmin` on the source
and defers VACUUM there until the snapshot completes.

# `args`

```elixir
@type args() :: %{
  :snapshot_name =&gt; String.t(),
  :consistent_point =&gt; Replicant.lsn(),
  :connection =&gt; keyword(),
  :publication =&gt; [String.t()],
  :sink =&gt; module(),
  :reply_to =&gt; pid(),
  optional(:mode) =&gt; :sink_owned | :lib
}
```

# `start`

```elixir
@spec start(args()) :: pid()
```

Spawn + LINK the snapshotter to the caller (the Connection) so it is torn down with the pipeline. Returns the pid.

---

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