BloomQuery<T> constructor

BloomQuery<T>({
  1. required List key,
  2. required Future<T> fetch(),
  3. Duration staleTime = const Duration(minutes: 5),
  4. Duration cacheTime = const Duration(minutes: 30),
  5. bool enabled = true,
  6. T? initialData,
})

Creates a BloomQuery and immediately checks cache freshness or initiates a fetch if enabled.

If initialData is provided and no cache entry exists for key, the query initializes in QueryStatus.success with that data and writes it to BloomData without firing an initial fetch.

Implementation

BloomQuery({
  required this.key,
  required this.fetch,
  this.staleTime = const Duration(minutes: 5),
  this.cacheTime = const Duration(minutes: 30),
  this.enabled = true,
  T? initialData,
}) {
  final cachedEntry = BloomData.getEntry<dynamic>(key);
  T? effectiveData;
  bool isStaleInitial;

  if (cachedEntry != null) {
    effectiveData = cachedEntry.data as T?;
    isStaleInitial = cachedEntry.shouldRevalidate;
  } else if (initialData != null) {
    effectiveData = initialData;
    isStaleInitial = false;
    BloomData.putEntry<T>(
      QueryCacheEntry<T>(
        key: key,
        data: initialData,
        updatedAt: DateTime.now(),
        staleTime: staleTime,
        cacheTime: cacheTime,
        isStale: false,
      ),
    );
  } else {
    effectiveData = null;
    isStaleInitial = true;
  }

  _data = signal<T?>(effectiveData);
  _status = signal<QueryStatus>(
    effectiveData != null ? QueryStatus.success : QueryStatus.idle,
  );
  _error = signal<Object?>(null);
  _isFetching = signal<bool>(false);
  _isStale = signal<bool>(isStaleInitial);

  _invalidationSub = BloomData.onInvalidated(key).listen((_) {
    _isStale.value = true;
    if (enabled && !_isDisposed) {
      refetch();
    }
  });

  if (enabled) {
    final entry = BloomData.getEntry<dynamic>(key);
    if (entry == null || entry.shouldRevalidate) {
      _executeFetch();
    }
  }
}