getAll<T> method
Retrieves multiple values associated with the given keys
.
Returns a map where the keys are the original keys and the values are the retrieved values. If a key is not found in the cache or its value is expired, it will not be included in the returned map.
If refreshCallbacks
is provided and an item is stale according to its policy,
the callback for that key will be used to refresh the data based on the refresh strategy.
Throws a CacheException if there is an error retrieving the data.
Implementation
Future<Map<String, T>> getAll<T>(
List<String> keys, {
Map<String, Future<T> Function()>? refreshCallbacks,
CachePolicy? policy,
}) async {
try {
if (keys.isEmpty) {
return {};
}
// Check for empty keys
for (final key in keys) {
if (key.isEmpty) {
throw ArgumentError('Keys cannot be empty');
}
}
final result = <String, T>{};
final cacheItems = await _cacheAdapter.getAll(keys);
final keysToDelete = <String>[];
final effectivePolicy = policy ?? CachePolicy.defaultPolicy;
// Process cache hits
for (final entry in cacheItems.entries) {
final key = entry.key;
final cacheItem = entry.value;
if (cacheItem.isExpired) {
// Record cache miss in analytics
_analytics.recordMiss(key);
keysToDelete.add(key);
// If a refresh callback is provided for this key, use it to get fresh data
if (refreshCallbacks != null && refreshCallbacks.containsKey(key)) {
final freshValue = await refreshCallbacks[key]!();
await put(key, freshValue, policy: policy);
result[key] = freshValue;
}
continue;
}
// Check if the item is stale and needs refreshing
if (refreshCallbacks != null &&
refreshCallbacks.containsKey(key) &&
effectivePolicy.staleTime != null &&
cacheItem.isStale(effectivePolicy.staleTime!)) {
// Handle different refresh strategies
switch (effectivePolicy.refreshStrategy) {
case RefreshStrategy.backgroundRefresh:
// Update in the background without blocking
_refreshInBackground(
key, refreshCallbacks[key]!, effectivePolicy);
break;
case RefreshStrategy.immediateRefresh:
// Refresh immediately and return the fresh value
final freshValue = await refreshCallbacks[key]!();
await put(key, freshValue, policy: effectivePolicy);
result[key] = freshValue;
continue; // Skip the rest of the loop for this item
case RefreshStrategy.never:
// Do nothing, just use the cached value
break;
}
}
// Decompress the value if it's compressed
T? resultValue;
if (cacheItem.isCompressed &&
_compression != null &&
cacheItem.value is String) {
try {
final decompressedValue =
_compression.decompressString(cacheItem.value as String);
resultValue = decompressedValue as T?;
_log.fine('Decompressed value for key $key');
} catch (e) {
_log.warning('Failed to decompress value for key $key: $e');
resultValue = cacheItem.value as T?;
}
} else {
resultValue = cacheItem.value as T?;
}
// Update sliding expiry if needed
if (cacheItem.slidingExpiry != null) {
final updatedCacheItem = cacheItem.updateExpiry();
await _cacheAdapter.put(key, updatedCacheItem);
// Record cache hit in analytics
_analytics.recordHit(key);
result[key] = resultValue as T;
} else {
// Update access metadata
final updatedCacheItem = cacheItem.updateExpiry();
if (updatedCacheItem != cacheItem) {
await _cacheAdapter.put(key, updatedCacheItem);
}
// Record cache hit in analytics
_analytics.recordHit(key);
result[key] = resultValue as T;
}
}
// Process cache misses with refresh callbacks
if (refreshCallbacks != null) {
final missingKeys = keys.where((key) =>
!result.containsKey(key) &&
!keysToDelete.contains(key) &&
refreshCallbacks.containsKey(key));
for (final key in missingKeys) {
// Record cache miss in analytics
_analytics.recordMiss(key);
final freshValue = await refreshCallbacks[key]!();
await put(key, freshValue, policy: policy);
result[key] = freshValue;
}
}
// Delete expired items in batch
if (keysToDelete.isNotEmpty) {
await _cacheAdapter.deleteAll(keysToDelete);
}
return result;
} on HiveError catch (e) {
_log.severe('Failed to get data from cache (HiveError): $e');
throw CacheException('Failed to get data from cache: ${e.message}');
} catch (e) {
_log.severe('Failed to get data from cache (Unknown Error): $e');
throw CacheException('Failed to get data from cache: $e');
}
}