GenServer managing compute locks for cache-aside with stampede protection.
When a cache miss occurs, only one client is allowed to compute the value (the "computer"). All other clients requesting the same key block as "waiters" until the computer delivers the result or an error.
Stampede protection
Without stampede protection, a cache miss on a hot key causes N concurrent
clients to all independently compute the same expensive value. This module
serializes computation: only the first caller gets {:compute, hint},
subsequent callers block until the result arrives.
Timeout handling
If the computer does not deliver a result within compute_timeout_ms
(default 30 seconds), the next waiter in line is promoted to computer.
If there are no waiters, the lock is simply cleared.
ETS table
Compute locks are stored in :ferricstore_compute_locks as:
{key, computer_pid, waiters_list, started_at_ms, compute_hint}This table is owned by the GenServer process.
Summary
Functions
Returns a specification to start this module under a supervisor.
Attempts to fetch a key from the store, or initiates a compute lock.
Reports a compute error for a key.
Delivers the computed result for a key.
Starts the FetchOrCompute GenServer.
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec fetch_or_compute(binary(), pos_integer(), binary()) :: {:hit, binary()} | {:compute, binary()} | {:ok, binary()} | {:error, binary()}
Attempts to fetch a key from the store, or initiates a compute lock.
Parameters
key-- the cache key to look upttl_ms-- TTL in milliseconds for the value when storedhint-- an opaque string hint passed to the computer (e.g. a URL or function name to call)
Returns
{:hit, value}-- the key was found in the store{:compute, hint}-- the caller is the computer; it must callfetch_or_compute_result/3orfetch_or_compute_error/2{:ok, value}-- the caller was a waiter and received the result{:error, reason}-- the compute failed (error propagated to waiters)
Reports a compute error for a key.
Wakes all waiters with {:error, error_msg} and clears the compute lock.
Parameters
key-- the cache keyerror_msg-- error message to propagate to waiters
Returns
:ok
@spec fetch_or_compute_result(binary(), binary(), pos_integer()) :: :ok
Delivers the computed result for a key.
Stores the value in the Router with the given TTL, wakes all waiters
with {:ok, value}, and clears the compute lock.
Parameters
key-- the cache keyvalue-- the computed value to storettl_ms-- TTL in milliseconds
Returns
:ok
@spec start_link(keyword()) :: GenServer.on_start()
Starts the FetchOrCompute GenServer.
Options
:compute_timeout_ms-- timeout in milliseconds before a stalled computer is replaced (default: 30000)