get<T extends Object> method

  1. @override
Future<T?> get<T extends Object>(
  1. String key, [
  2. Fetch<T>? fetch,
  3. String? trace
])

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;
}