BloomQueryScope class
Global query cache manager and request deduplicator for Bloom JS Native applications.
BloomData provides a centralized, pure-Dart memory cache for asynchronous queries:
- Key Normalization: Deterministically serializes complex structured keys (Strings, Lists, Maps)
via
normalizeKey. - Request Deduplication: Collapses concurrent identical requests into a single in-flight
Futurevia deduplicate. - Cache Invalidation: Notifies active BloomQuery instances via invalidateQueries using prefix matching.
- Direct Manipulation: Allows optimistic cache writing via setQueryData and direct inspection via getQueryData.
- SSR Dehydration & Hydration: Serializes cache snapshots to JSON via dehydrate or dehydrateToScriptTag, and restores them on the client via hydrate or hydrateFromJson with zero redundant fetches.
SSR & Browser Compatibility
Pure Dart with zero Flutter or DOM dependencies. In SSR environments, BloomData can be pre-populated with server data before rendering or cleared between requests via clear.
Example
// Manually prime or update the cache
BloomData.setQueryData<User>(['user', 123], (old) => updatedUser);
// Invalidate all queries under the 'user' prefix
BloomData.invalidateQueries(['user']);
See also:
- BloomQuery, the reactive query coordinator that reads from and populates BloomData.
- BloomInfiniteQuery, for paginated and cursor-based infinite queries.
- BloomMutation, for executing mutations that invalidate or optimistically update BloomData. Request-isolated query cache scope holding private SSR state.
A BloomQueryScope owns its own cache entries, invalidation controllers,
and in-flight deduplication trackers. Concurrent SSR requests each run in
their own scope (via BloomData.runWithScope / BloomData.withRequestScope)
so identical keys such as ['user', 'current'] never collide across
requests sharing one Dart isolate.
The browser uses BloomData.browserScope implicitly. Explicitly shared public server data should use BloomData.sharedPublicScope via BloomData.runWithScope — never the per-request scope.
Scopes must be disposed after the request finishes (dispose) to close broadcast controllers and drop references. BloomData.withRequestScope does this automatically, including on errors. For streaming responses, keep the scope alive until the stream closes or is cancelled.
Constructors
- BloomQueryScope({String? debugLabel})
- Creates an isolated query cache scope.
Properties
- debugLabel → String?
-
Optional label for debugging (e.g.
'ssr-request','browser').final - hashCode → int
-
The hash code for this object.
no setterinherited
- isDisposed → bool
-
Whether dispose has been called. Using a disposed scope throws.
no setter
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
adoptEntryFrom(
BloomQueryScope source, List key) → void -
Copies a single entry from
sourceinto this scope (explicit public sharing). -
clear(
) → void - Clears entries, in-flight trackers, and controllers within this scope.
-
deduplicate<
T> (List key, Future< T> fetcher()) → Future<T> -
Deduplicates concurrent requests sharing
keywithin this scope only. -
dehydrate(
{bool shouldDehydrate(QueryCacheEntry entry)?, dynamic serialize(dynamic data, List key)?}) → Map< String, dynamic> - Serializes only this scope's cache — never another request's state.
-
dehydrateToScriptTag(
{Map< String, dynamic> ? state, String id = '__BLOOM_DATA__', bool shouldDehydrate(QueryCacheEntry entry)?, dynamic serialize(dynamic data, List key)?}) → String -
Serializes this scope into a safe
<script type="application/json">tag. -
dispose(
) → void - Closes controllers and drops all state. The scope must not be reused.
-
getEntry<
T> (List key) → QueryCacheEntry< T> ? -
Retrieves the raw QueryCacheEntry for
keyfrom this scope. -
getQueryData<
T> (List key) → T? -
Retrieves non-expired cached query data for
keyfrom this scope. -
hydrate(
Map< String, dynamic> dehydratedState, {dynamic deserialize(dynamic data, List key)?}) → void - Restores entries into this scope only.
-
hydrateFromJson(
String jsonString, {dynamic deserialize(dynamic data, List key)?}) → void - Parses JSON and restores entries into this scope.
-
invalidateQueries(
List keyPrefix) → void -
Invalidates all cached queries matching
keyPrefixwithin this scope. -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
onInvalidated(
List key) → Stream< void> -
Broadcast stream emitting on invalidation of
keywithin this scope. -
putEntry<
T> (QueryCacheEntry< T> entry) → void - Directly inserts or overwrites a QueryCacheEntry in this scope.
-
setQueryData<
T> (List key, T updater(T? oldData)) → void -
Directly updates cached query data for
keywithin this scope. -
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited