get<T extends Object> method
Retrieves a value from storage by key.
If the key doesn't exist and a fetch function is provided,
it will be called to retrieve the value, which will then be stored.
Implementation
@override
Future<T?> get<T extends Object>(
String key, [
Fetch<T>? fetch,
String? trace,
]) async {
final cache = _getCache<T>();
await cache.open();
T? value = await cache.get(key);
if (value == null && fetch != null) {
await Future.delayed(
Duration(
milliseconds: Random().nextInt(400) + 150,
),
);
}
final String identity = trace ?? cache.lockIdentity;
if (await cache.isExtLocked(key, identity)) {
await Future.delayed(const Duration(milliseconds: 200));
return get<T>(key, fetch, trace);
} else if (isKeyInFlight<T>(key)) {
return inFlightRequest<T>(key);
}
markAsInFlight<T>(key);
value ??= await cache.get(key);
if (value == null && fetch != null) {
bool hasLock = await cache.acquireLock(key, identity);
if (!hasLock) {
throw Exception('Unable to achieve lock on key $key');
}
final fetchedValue = await fetch();
if (fetchedValue != null) {
await put<T>(key, fetchedValue, trace);
return fetchedValue;
}
} else if (value != null) {
resolveInFlightRequest<T>(key, value);
}
removeInFlight<T>(key);
await cache.releaseLock(key, trace ?? '');
return value;
}