// ignore_for_file: close_sinks import 'dart:async'; import 'package:rxdart/rxdart.dart'; import 'package:rxdart/subjects.dart'; class FutureRequestManager { FutureRequestManager([this.cacheLimit = 10]); final int cacheLimit; final Map> _requests = {}; Future performRequest({ String? uniqueQueryKey, bool? overrideCache, required Future Function() requestFn, }) { uniqueQueryKey = _requestKey(uniqueQueryKey); overrideCache ??= false; // If we don't want to use the cache, clear it for this request. if (overrideCache) { clearRequest(uniqueQueryKey); } // Remove the first cached result if we have reached the specified limit, // since we will be adding another. if (!_requests.containsKey(uniqueQueryKey) && _requests.length >= cacheLimit) { _requests.remove(_requests.keys.first); } // Return the cached query result or set it to the new value. return _requests[uniqueQueryKey] ??= requestFn(); } void clearRequest(String? key) => _requests.remove(_requestKey(key)); void clear() => _requests.keys.toList().forEach(clearRequest); } class StreamRequestManager { StreamRequestManager([this.cacheLimit = 10]); final int cacheLimit; final Map> _streamSubjects = {}; final Map> _requestSubscriptions = {}; Stream performRequest({ String? uniqueQueryKey, bool? overrideCache, required Stream Function() requestFn, }) { uniqueQueryKey = _requestKey(uniqueQueryKey); overrideCache ??= false; // If we don't want to use the cache, clear it for this request. if (overrideCache) { clearRequest(uniqueQueryKey); } // If this request was made previously, return its value stream. if (_streamSubjects.containsKey(uniqueQueryKey)) { return _streamSubjects[uniqueQueryKey]!.stream; } // Remove the first cached result if we have reached the specified limit, // since we will be adding another. if (_streamSubjects.isNotEmpty && _streamSubjects.length >= cacheLimit) { clearRequest(_streamSubjects.keys.first); } // Create a subscription that stores the latest result in the behavior subject. final streamSubject = BehaviorSubject(); _requestSubscriptions[uniqueQueryKey] = requestFn() .asBroadcastStream() .listen((result) => streamSubject.add(result)); _streamSubjects[uniqueQueryKey] = streamSubject; return streamSubject.stream; } void clearRequest(String? key) { key = _requestKey(key); _streamSubjects.remove(key)?.close(); _requestSubscriptions.remove(key)?.cancel(); } void clear() => { ..._streamSubjects.keys, ..._requestSubscriptions.keys, }.forEach(clearRequest); } String _requestKey(String? key) => key == null || key.isEmpty ? '__DEFAULT_KEY__' : key;