Skuld.Query.Cache (skuld v0.3.0)
View SourceComposable caching layer for Query.Contract queries.
Provides:
- Cross-batch result caching — identical queries across batch rounds return cached results without re-executing
- Within-batch request deduplication — identical queries in the same batch round are sent to the executor only once, with the result fanned out to all requesting fibers
Usage
comp
|> QueryCache.with_executor(Users, Users.EctoExecutor)
|> FiberPool.with_handler()
|> Comp.run()
# Multiple contracts (shared cache scope):
comp
|> QueryCache.with_executors([
{Users, Users.EctoExecutor},
{Orders, Orders.EctoExecutor}
])
|> FiberPool.with_handler()
|> Comp.run()Cache Scope
The cache is scoped per computation run. It's initialised as an empty map
by Comp.scoped and cleaned up on scope exit. No TTL, no eviction.
Multiple with_executors/with_executor calls share a single cache scope.
The first call creates the cache; subsequent calls reuse the existing cache
and register their executors against it. Only the outermost scope performs
cleanup.
Cache Key
{batch_key, op_struct} where:
batch_keyis{ContractModule, :query_name}op_structis the operation struct (e.g.%Users.GetUser{id: "123"})
Structural equality on Elixir structs provides correct comparison.
Per-Query Opt-Out
Queries declared with cache: false bypass caching entirely:
deffetch get_random_user() :: User.t(), cache: falseError Handling
Executor failures are not cached. When an executor produces a Throw, the error propagates normally and the cache is not polluted — subsequent requests for the same query go to the executor again.
Summary
Functions
Install a caching-wrapped executor for a single contract.
Install caching-wrapped executors for multiple contracts.
Functions
@spec with_executor(Skuld.Comp.Types.computation(), module(), module()) :: Skuld.Comp.Types.computation()
Install a caching-wrapped executor for a single contract.
Shorthand for with_executors(comp, [{contract_module, executor_module}]).
@spec with_executors(Skuld.Comp.Types.computation(), [{module(), module()}]) :: Skuld.Comp.Types.computation()
Install caching-wrapped executors for multiple contracts.
Initialises a scoped cache and registers caching-wrapped executors for
all query operations in each contract. Queries with cacheable: false
(from deffetch ..., cache: false) are registered with raw dispatch
that bypasses the cache entirely.
Example
comp
|> QueryCache.with_executors([
{Users, Users.EctoExecutor},
{Orders, Orders.EctoExecutor}
])
|> FiberPool.with_handler()
|> Comp.run()