putAsync<T> method
Future<void>
putAsync<T>(
- String key,
- T value, {
- Duration? expiry,
- Duration? slidingExpiry,
- CachePolicy? policy,
Stores a value in the cache with the given key
asynchronously.
This method is similar to put, but uses asynchronous compression for large strings, which can improve performance by avoiding blocking the main thread.
The expiry
parameter can be used to set an optional expiry time for the data.
The slidingExpiry
parameter can be used to set an optional sliding expiry time for the data.
The policy
parameter can be used to set a cache policy for the data.
If both individual parameters (expiry, slidingExpiry) and a policy are provided, the individual parameters will take precedence over the policy.
Throws an ArgumentError if the key is empty. Throws a CacheException if there is an error storing the data.
Implementation
Future<void> putAsync<T>(String key, T value,
{Duration? expiry, Duration? slidingExpiry, CachePolicy? policy}) async {
if (key.isEmpty) {
throw ArgumentError('Key cannot be empty');
}
try {
final effectivePolicy = policy ?? CachePolicy.defaultPolicy;
final effectiveExpiry = expiry ?? effectivePolicy.expiry;
final effectiveSlidingExpiry =
slidingExpiry ?? effectivePolicy.slidingExpiry;
// Apply encryption if needed
if (effectivePolicy.encrypt && !_cacheAdapter.enableEncryption) {
_log.warning(
'Encryption requested but not supported by the adapter. Data will be stored unencrypted.');
}
// Apply compression if needed
dynamic finalValue = value;
bool isCompressed = false;
int? originalSize;
double? compressionRatio;
if (effectivePolicy.compression != CompressionMode.never &&
_compression != null &&
value is String) {
// For auto mode, check if compression is beneficial
if (effectivePolicy.compression == CompressionMode.auto) {
if (_compression.shouldCompress(value)) {
// Compress the value asynchronously
originalSize = value.length * 2;
final compressedValue =
await _compression.compressStringAsync(value);
compressionRatio = originalSize / (compressedValue.length * 2);
// Only use compression if it actually reduces the size
if (compressionRatio > 1.1) {
// At least 10% reduction
finalValue = compressedValue;
isCompressed = true;
_log.fine(
'Compressed value for key $key with ratio $compressionRatio');
}
}
} else if (effectivePolicy.compression == CompressionMode.always) {
// Always compress
originalSize = value.length * 2;
final compressedValue = await _compression.compressStringAsync(value);
compressionRatio = originalSize / (compressedValue.length * 2);
finalValue = compressedValue;
isCompressed = true;
_log.fine(
'Compressed value for key $key with ratio $compressionRatio');
}
}
final cacheItem = CacheItem<T>(
value: finalValue as T,
expiry: effectiveExpiry != null
? DateTime.now().add(effectiveExpiry)
: null,
slidingExpiry: effectiveSlidingExpiry,
priority: effectivePolicy.priority,
isCompressed: isCompressed,
originalSize: originalSize,
compressionRatio: compressionRatio,
);
// Use the SizeEstimator for more accurate size estimation
final estimatedSize = SizeEstimator.estimateCacheItemSize(
finalValue,
hasExpiry: effectiveExpiry != null,
hasSlidingExpiry: effectiveSlidingExpiry != null,
isCompressed: isCompressed,
originalSize: originalSize,
);
// Check if the item exceeds the maximum size (if specified)
if (effectivePolicy.maxSize != null) {
if (estimatedSize > effectivePolicy.maxSize!) {
_log.warning(
'Item exceeds maximum size: $estimatedSize > ${effectivePolicy.maxSize}');
throw CacheException(
'Item exceeds maximum size: $estimatedSize > ${effectivePolicy.maxSize}');
}
}
// Record the put operation in analytics
_analytics.recordPut(key, estimatedSize);
await _cacheAdapter.put(key, cacheItem);
// Check if we need to evict items
if (_eviction != null) {
await _eviction.checkAndEvict();
}
} on HiveError catch (e) {
_log.severe('Failed to put data into cache (HiveError): $e');
throw CacheException('Failed to put data into cache: ${e.message}');
} catch (e) {
_log.severe('Failed to put data into cache (Unknown Error): $e');
throw CacheException('Failed to put data into cache: $e');
}
}