AshCache.Coalesce (AshCache v0.1.0)

Copy Markdown View Source

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.

Summary

Functions

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.

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

Functions

join(key)

@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(key, outcome)

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

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