Skip to content

Commit 85e1171

Browse files
authored
Add in-memory cache to store version listings (#3163)
1 parent 46f79d5 commit 85e1171

File tree

1 file changed

+25
-4
lines changed

1 file changed

+25
-4
lines changed

lib/src/source/hosted.dart

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,15 @@ class BoundHostedSource extends CachedSource {
341341
return result;
342342
}
343343

344+
/// An in-memory cache to store the cached version listing loaded from
345+
/// [_versionListingCachePath].
346+
///
347+
/// Invariant: Entries in this cache are the parsed version of the exact same
348+
/// information cached on disk. I.e. if the entry is present in this cache,
349+
/// there will not be a newer version on disk.
350+
final Map<PackageRef, Pair<DateTime, Map<PackageId, _VersionInfo>>>
351+
_responseCache = {};
352+
344353
/// If a cached version listing response for [ref] exists on disk and is less
345354
/// than [maxAge] old it is parsed and returned.
346355
///
@@ -351,26 +360,35 @@ class BoundHostedSource extends CachedSource {
351360
Future<Map<PackageId, _VersionInfo>> _cachedVersionListingResponse(
352361
PackageRef ref,
353362
{Duration maxAge}) async {
363+
if (_responseCache.containsKey(ref)) {
364+
final cacheAge = DateTime.now().difference(_responseCache[ref].first);
365+
if (maxAge == null || maxAge > cacheAge) {
366+
// The cached value is not too old.
367+
return _responseCache[ref].last;
368+
}
369+
}
354370
final cachePath = _versionListingCachePath(ref);
355371
final stat = io.File(cachePath).statSync();
356372
final now = DateTime.now();
357373
if (stat.type == io.FileSystemEntityType.file) {
358374
if (maxAge == null || now.difference(stat.modified) < maxAge) {
359375
try {
360-
final cachedDoc = jsonDecode(await readTextFileAsync(cachePath));
376+
final cachedDoc = jsonDecode(readTextFile(cachePath));
361377
final timestamp = cachedDoc['_fetchedAt'];
362378
if (timestamp is String) {
363-
final cacheAge =
364-
DateTime.now().difference(DateTime.parse(timestamp));
379+
final parsedTimestamp = DateTime.parse(timestamp);
380+
final cacheAge = DateTime.now().difference(parsedTimestamp);
365381
if (maxAge != null && cacheAge > maxAge) {
366382
// Too old according to internal timestamp - delete.
367383
tryDeleteEntry(cachePath);
368384
} else {
369-
return _versionInfoFromPackageListing(
385+
var res = _versionInfoFromPackageListing(
370386
cachedDoc,
371387
ref,
372388
Uri.file(cachePath),
373389
);
390+
_responseCache[ref] = Pair(parsedTimestamp, res);
391+
return res;
374392
}
375393
}
376394
} on io.IOException {
@@ -402,6 +420,9 @@ class BoundHostedSource extends CachedSource {
402420
},
403421
),
404422
);
423+
// Delete the entry in the in-memory cache to maintain the invariant that
424+
// cached information in memory is the same as that on the disk.
425+
_responseCache.remove(ref);
405426
} on io.IOException catch (e) {
406427
// Not being able to write this cache is not fatal. Just move on...
407428
log.fine('Failed writing cache file. $e');

0 commit comments

Comments
 (0)