DejaClient
The shared query cache: a registry of entries keyed by QueryKey, plus
invalidation, manual reads/writes, per-prefix defaults, and eviction of idle entries.
public sealed class DejaClient : IDisposableRegistration#
AddDeja (extension)#
Registers DejaOptions (singleton) and DejaClient
(Scoped). Scoped is the only correct lifetime across both hosting models:
per browser tab on WebAssembly, per user circuit on Blazor Server — a singleton on Server
would share one user's cached API responses with every other user. Do not "optimise" this
to a singleton.
DejaClient(DejaOptions?)#
Creates a standalone client (e.g. for tests), optionally with non-default options, and starts the eviction loop.
Reading#
GetData<T>#
The cached data under key, or default when the key is absent,
has no data yet, or was stored with a different T.
TryGetData<T>#
Reads the cached data under key. Returns false when the key is absent or has
no data. A key stored with a different T also returns false rather than
throwing — it almost always means two call sites disagree about the key's shape, and is
reported as a debug-level warning.
GetState#
A read-only snapshot of the entry under key — data presence, fetching flag,
invalidation, subscriber count, timestamps — or null when absent. Values are coherent at
the moment of the call and do not update afterwards. This site's cache inspectors poll it.
Writing#
SetData<T> (value)#
Writes data under key (creating the entry when absent) and
notifies every subscribed query. The manual alternative to invalidation when the new value
is already known — e.g. appending a mutation result to a cached list. Throws
InvalidOperationException when the key holds data of a different type.
SetData<T> (updater)#
Transforms the cached value under key: updater receives the
current data (or default when none) and returns the new value. The building
block of the optimistic write pattern.
Invalidation and refetch#
InvalidateAsync#
Marks every entry matching key stale — by prefix unless
InvalidateOptions.Exact — and refetches per
InvalidateOptions.RefetchType: by default entries with live subscribers
refetch in the background (existing data stays on screen, no loading flash), while
subscriber-less entries stay marked and refetch when a component next mounts on them. The
returned task completes when the triggered refetches settle.
InvalidateAllAsync#
Invalidates every entry in the cache; active entries refetch in the background.
RefetchAsync#
Refetches every entry matching key that has a fetch function, regardless of
staleness. Failures are recorded on the entries, not thrown.
Removal#
Remove#
Removes every entry matching key, cancelling in-flight fetches. Subscribed
queries keep rendering their last data; their next Execute starts from an
empty entry.
Clear#
Removes every entry, cancelling in-flight fetches.
Defaults and lifecycle#
SetDefaults#
Registers defaults for every key starting with prefix, replacing any previous
defaults for the same prefix. Precedence, most specific wins: per-query value > longest
matching prefix > DejaOptions — registration order does
not matter.
Dispose#
Stops the eviction timer and drops every entry; called by DI when the scope ends.
Eviction behaviour#
- Entries with live subscribers are never evicted.
- A subscriber-less entry is dropped once its cache time elapses (checked every
EvictionInterval). - With
MaxEntriesset, least-recently-used subscriber-less entries are evicted first when the cap is exceeded; the cache may exceed the cap while everything in it is on screen. - Executing a query against a key that already holds a different data type throws — two call sites disagreeing about a key's shape is a bug that silent replacement would mask.