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 Future via 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 source into 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 key within 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 key from this scope.
getQueryData<T>(List key) → T?
Retrieves non-expired cached query data for key from 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 keyPrefix within 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 key within 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 key within this scope.
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited