# `Replicant.Spill.Reader`
[🔗](https://github.com/baselabs/replicant/blob/v0.3.1/lib/replicant/spill/reader.ex#L1)

A lazy, SINGLE-PASS `Enumerable` over a spilled transaction's changes (spec §5): it streams the
on-disk frames (in commit order) followed by the still-resident in-memory tail, rejects any change
whose `subxid` is in the aborted set, and stamps `commit_lsn` at replay (streamed changes have no
LSN before commit; the `ordinal` was stamped at accumulation from the shared per-txn counter and is
preserved). It is value-free BY CONSTRUCTION — a `File` read or
`binary_to_term` fault raises `Replicant.Spill.Error` (fixed reason, no bytes), never a raw-byte
exception, even though the sink forces this enumeration inside its own DB transaction (spec §11).

Delivered as `%Transaction{changes: reader}` for a spilled transaction; the sink MUST consume it
within the delivery call (single-pass; reading a deleted file raises `Spill.Error`, fail-loud).

# `t`

```elixir
@type t() :: %Replicant.Spill.Reader{
  aborted: MapSet.t(non_neg_integer()),
  commit_lsn: Replicant.lsn(),
  path: String.t(),
  tail: [{non_neg_integer(), Replicant.Change.t()}]
}
```

# `new`

```elixir
@spec new(
  String.t(),
  [{non_neg_integer(), Replicant.Change.t()}],
  MapSet.t(),
  Replicant.lsn()
) :: t()
```

Build a Reader over spilled file `path` + the in-memory `tail` (stored newest-first, reversed to
commit order here), filtering `aborted` subxids, stamping `commit_lsn`.

---

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