QoraClientConfig
Overview
QoraClientConfig is passed to the QoraClient constructor and sets defaults for every query in the client's lifetime. Individual queries can override any field via QoraOptions.
final client = QoraClient(
config: QoraClientConfig(
defaultOptions: QoraOptions(
staleTime: Duration(minutes: 5),
gcTime: Duration(minutes: 10),
retryCount: 3,
),
debugMode: kDebugMode,
maxCacheSize: 200,
refetchOnMount: true,
errorMapper: (error, stack) => QoraException(
'$error',
originalError: error,
stackTrace: stack,
),
),
);
Constructor
const QoraClientConfig({
QoraOptions defaultOptions = const QoraOptions(),
QoraException Function(Object error, StackTrace? stackTrace)? errorMapper,
bool debugMode = false,
int? maxCacheSize,
void Function(List<dynamic> key)? onCacheEvict,
void Function(Object error, StackTrace? stackTrace, List<dynamic> queryKey)? onBackgroundFetchError,
bool refetchOnMount = true,
ReconnectStrategy reconnectStrategy = const ReconnectStrategy(),
})
Fields
defaultOptions
final QoraOptions defaultOptions
Default: QoraOptions() (all defaults)
The baseline QoraOptions applied to every query. Per-query options are merged on top using QoraOptions.merge().
defaultOptions: QoraOptions(
staleTime: Duration(minutes: 5),
gcTime: Duration(minutes: 10),
retryCount: 3,
retryDelay: Duration(seconds: 1),
),
→ See QoraOptions for all available fields.
errorMapper
final QoraException Function(Object error, StackTrace? stackTrace)? errorMapper
Default: null (errors are stored as-is)
Transforms raw errors into QoraException before they are stored in Failure states. Use this to normalise API-specific error types into a consistent shape across your app:
errorMapper: (error, stackTrace) {
if (error is DioException) {
return QoraException(
error.message ?? 'Network error',
originalError: error,
stackTrace: stackTrace,
);
}
return QoraException('$error', originalError: error, stackTrace: stackTrace);
},
When set, all Failure.error values will be QoraException instances, giving you a single type to check in your error handlers.
debugMode
final bool debugMode
Default: false
Enables verbose print logging to the console. Logs:
- Cache hits (fresh and stale)
- Cache misses
- Fetch attempts and retry delays
- Deduplication events
- Lazy eviction and GC removals
setQueryDataandinvalidatecalls- Client disposal
// Enable only in debug builds
debugMode: kDebugMode,
maxCacheSize
final int? maxCacheSize
Default: null (unbounded)
Maximum number of query entries in the cache. When the limit is reached, the least-recently-used inactive entry is evicted to make room. Active entries (those with watchQuery subscribers) are never forcibly evicted.
maxCacheSize: 100, // cap memory usage in list-heavy apps
100–200. Monitor client.debugInfo()['total_queries'] to tune this for your usage patterns.onCacheEvict
final void Function(List<dynamic> key)? onCacheEvict
Default: null
Callback invoked whenever a cache entry is evicted: via LRU pressure, GC timer, removeQuery, or clear. Receives the normalised key of the evicted entry.
onCacheEvict: (key) {
// Log or sync with persistent storage
print('[Cache] evicted: $key');
persistentStore.delete(key.toString());
},
onBackgroundFetchError
final void Function(Object error, StackTrace? stackTrace, List<dynamic> queryKey)? onBackgroundFetchError
Default: null
Callback invoked when a background fetch triggered by watchQuery fails. Background fetches run inside unawaited futures and without this callback the re-thrown error would crash the current async Zone.
The error has already been stored in the query's Failure state by the time this callback fires. Use this callback for logging, telemetry, or crash reporting, not for error recovery.
onBackgroundFetchError: (error, stackTrace, key) {
crashReporter.record(error, stackTrace);
},
refetchOnMount
final bool refetchOnMount
Default: true
Global default for whether watchQuery should trigger a fetch on the first subscription, even when cached data already exists.
true: always refetch on mount (recommended for most apps)false: only fetch if no data exists; skip if any cached state is present
Can be overridden per query via QoraOptions.refetchOnMount.
// Global: don't refetch if any data exists
refetchOnMount: false,
// Per-query override: always refetch this specific query
options: QoraOptions(refetchOnMount: true),
reconnectStrategy
final ReconnectStrategy reconnectStrategy
Default: const ReconnectStrategy() (5 concurrent, 100 ms jitter)
Controls how QoraClient replays paused queries when connectivity is restored. Without batching, all paused queries would fire simultaneously: the "thundering herd" problem. ReconnectStrategy introduces concurrency limits and random jitter between batches:
reconnectStrategy: const ReconnectStrategy(
maxConcurrent: 5, // Replay 5 queries at a time
jitter: Duration(milliseconds: 200), // Random wait between batches
),
Named constructors for common scenarios:
// Default: balanced for most apps
const ReconnectStrategy()
// All queries replay at once (useful in tests)
ReconnectStrategy.instant()
// Conservative: 2 queries at a time, 500 ms jitter
ReconnectStrategy.conservative()
| Named constructor | maxConcurrent | jitter |
|---|---|---|
ReconnectStrategy() | 5 | 100 ms |
ReconnectStrategy.instant() | 999 | 0 ms |
ReconnectStrategy.conservative() | 2 | 500 ms |
ReconnectStrategy.conservative() or lower maxConcurrent to avoid spiking your backend after a connectivity gap.Recommended Setup
import 'package:flutter/foundation.dart';
import 'package:qora/qora.dart';
final qoraClient = QoraClient(
config: QoraClientConfig(
defaultOptions: const QoraOptions(
staleTime: Duration(minutes: 5),
gcTime: Duration(minutes: 10),
retryCount: 3,
retryDelay: Duration(seconds: 1),
networkMode: NetworkMode.online,
),
debugMode: kDebugMode,
maxCacheSize: 200,
refetchOnMount: true,
onBackgroundFetchError: (error, stackTrace, key) =>
crashReporter.record(error, stackTrace),
reconnectStrategy: const ReconnectStrategy(
maxConcurrent: 5,
jitter: Duration(milliseconds: 100),
),
),
);
For Flutter apps, pass this client to QoraScope at the root of your widget tree so all widgets can access it via context.qora.
→ See Network Aware Guide for the full offline setup walkthrough.
QoraOptions
Per-query configuration that overrides QoraClientConfig defaults. Pass to fetchQuery or watchQuery to customise caching, retries, staleness, and polling.
Mutation API
Complete API reference for MutationController, MutationState, MutationOptions, MutationUpdate, and mutation observability on QoraClient.