get method
Retrieves a value from the cache by its key.
Returns the cached value associated with the key if it exists and has not expired.
If the key does not exist or has expired, returns null.
Throws an exception if the key is null or empty.
Implementations should handle deserialization of the stored value if necessary.
- Parameters:
key: A non-null, non-empty string representing the cache key.
- Returns: The cached value, or
nullif not found or expired.
Implementation
@override
Future<dynamic> get(String key) async {
if (key.isEmpty) {
throw ArgumentError('Cache key cannot be empty');
}
final filePath = _getFilePath(key);
final file = File(filePath);
if (!await file.exists()) {
_stats.misses++;
await _saveMetadata();
return null;
}
try {
var encodedData = await file.readAsString();
final isCompressed =
encodedData.startsWith('H4sI'); // Gzip magic bytes in base64
Map<String, dynamic> data;
if (isCompressed) {
// Decompress the data
try {
final compressedBytes = base64Decode(encodedData);
final decompressedBytes = gzip.decode(compressedBytes);
encodedData = utf8.decode(decompressedBytes);
data = jsonDecode(encodedData);
} catch (e) {
// If decompression fails, treat as corrupted
throw const FormatException('Failed to decompress cache data');
}
} else {
data = jsonDecode(encodedData);
}
final expiresAt = DateTime.parse(data['expires_at']);
final now = DateTime.now();
if (now.isAfter(expiresAt)) {
// Cache expired, remove file
await forget(key);
_stats.misses++;
_stats.expirations++;
await _saveMetadata();
return null;
}
// Update statistics
_stats.hits++;
await _saveMetadata();
// Return the value
return data['value'];
} catch (e) {
// If file is corrupted, remove it
try {
await file.delete();
} catch (_) {
// Ignore deletion errors
}
_stats.misses++;
await _saveMetadata();
return null;
}
}