# `Electric.Shapes.Consumer.Materializer`
[🔗](https://github.com/electric-sql/electric/tree/%40core/sync-service%401.8.1/packages/sync-service/lib/electric/shapes/consumer/materializer.ex#L1)

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `delete_link_values`

```elixir
@spec delete_link_values(Electric.stack_id(), Electric.shape_handle()) :: :ok
```

Removes the cached link values for `shape_handle` from the shared ETS table.
Safe to call even if the table does not exist (e.g. after a stack shutdown).

# `get_all_as_refs`

# `get_link_values`

Returns the current set of materialized link values for a shape.
Checks the shared ETS cache first (written after each committed transaction);
falls back to a synchronous GenServer call if the cache has no entry yet.

# `handle_continue`

# `init`

# `init_link_values_table`

```elixir
@spec init_link_values_table(stack_id :: term()) :: :ets.table() | :undefined
```

Creates the per-stack ETS table that caches link values for all materializers
in a stack. Called by `ConsumerRegistry` during stack initialization. Idempotent —
safe to call when the table already exists.

# `link_values_table_name`

```elixir
@spec link_values_table_name(Electric.stack_id()) :: atom()
```

# `name`

# `name`

# `new_changes`

```elixir
@spec new_changes(
  map(),
  [Electric.Replication.Changes.change()]
  | {Electric.Replication.LogOffset.t(), Electric.Replication.LogOffset.t()},
  keyword()
) :: :ok
```

# `read_history_up_to_subscribed`

Replay all of the source shape's persisted history (snapshot + log) up to
`state.subscribed_offset` so the materializer's value_counts reflect the
on-disk state on startup.

`Storage.get_log_stream/3` returns at most one chunk per call **for
snapshot chunks** — but for the main log it returns the entire requested
range `[min_offset, subscribed_offset]` in one call. So we iterate
through snapshot chunks using `Storage.get_chunk_end_log_offset/2`,
and as soon as the iteration would step into the main log we stop:
the previous call already streamed everything up to the subscribed
offset. Iterating into the main log would re-read entries already
applied, producing duplicate inserts that crash the materializer.

The subscribed_offset is the Consumer's latest_offset at the time of
subscription. We only read up to this offset to avoid duplicates — any
changes after this offset will be delivered via new_changes messages
from the Consumer.

# `start_link`

# `subscribe`

# `subscribe`

# `wait_until_ready`

# `whereis`

# `whereis`

---

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