flexible<T> method
Stale while revalidate. The value is fresh for fresh. After that
it is stale for stale more: it is still returned right away, and
one caller refreshes it in the background. After fresh + stale
it is gone, and the next call waits for compute.
A null stale keeps the value until a refresh replaces it. Use it
when an old value beats none, like rates from a provider that can be
down: when compute fails, callers still get the last good value.
decode works like in remember. The driver must support locks.
int count = await cache.flexible<int>(
'users',
Duration(minutes: 5),
Duration(minutes: 10),
countUsers,
);
Implementation
Future<T> flexible<T>(
String key,
Duration fresh,
Duration? stale,
FutureOr<T> Function() compute, {
T Function(Object? json)? decode,
}) async {
String fullKey = await itemKey(key);
String createdKey = '${CacheConstants.flexibleCreatedPart}$fullKey';
Map<String, dynamic> found = await driver.many(<String>[
fullKey,
createdKey,
]);
Object? cached = found[fullKey];
Object? created = found[createdKey];
if (cached == null || created is! int) {
return await _once<T>(
fullKey,
() => _computeFlexible<T>(fullKey, createdKey, fresh, stale, compute),
);
}
if (clock.nowMs() - created >= fresh.inMilliseconds) {
_refreshFlexible<T>(fullKey, createdKey, fresh, stale, compute).ignore();
}
return _decode<T>(cached, decode);
}