# `AshCache.Coalesce`
[🔗](https://github.com/Undeadlol1/ash_cache/blob/v0.1.0/lib/ash_cache/coalesce.ex#L1)

Lets identical cache misses on one server share a single data-layer read.

When a popular entry runs out, every request arriving before it is cached
again would read the data layer. Instead, the first request for a cache
key becomes the *leader* and reads; the others wait and get its records.
Requests share a read only when their whole cache key is equal, so actor
and tenant isolation is the same as for cached entries.

If the leader's read fails or its process dies, the waiters start over and
one of them leads the next read. If the leader takes longer than
`config :ash_cache, rebuild_timeout: ms` (default 5 seconds), each waiter
reads for itself, so a stuck read never blocks anyone for good.

This works per server, whatever the store: on several servers, each server
makes at most one read per key at a time. Built-in options were checked
first: `Cachex.fetch/4` runs the rebuild in another process, which Ash's
read hooks cannot hand it, and Nebulex's `fetch_or_store` documents that
concurrent misses can each run the function.

# `join`

```elixir
@spec join(term()) :: :lead | {:shared, term()} | :retry | :alone
```

Joins the read for `key`. Returns `:lead` when the caller must read and
then call `release/2`, `{:shared, records}` with the leader's records,
`:retry` when the leader failed (look in the cache again: another waiter
may already have rebuilt it, then join again), or `:alone` when the leader
took too long and the caller should just read.

# `release`

```elixir
@spec release(term(), {:ok, term()} | :failed) :: :ok
```

Tells everyone waiting on `key` the leader's outcome: `{:ok, records}` or `:failed`.

---

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