Skip to content

Commit d8be4e6

Browse files
committed
cache trend scores in backend
1 parent 1db79bb commit d8be4e6

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

app/lib/fake/backend/fake_download_counts.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,9 @@ Future<void> generateFake30DaysTotals(Map<String, int> totals) async {
4848
.writeBytesWithRetry(
4949
downloadCounts30DaysTotalsFileName, jsonUtf8Encoder.convert(totals));
5050
}
51+
52+
Future<void> generateFakeTrendScores(Map<String, int> totals) async {
53+
await storageService
54+
.bucket(activeConfiguration.reportsBucketName!)
55+
.writeBytesWithRetry(trendScoreFileName, jsonUtf8Encoder.convert(totals));
56+
}

app/lib/service/download_counts/backend.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,20 @@ class DownloadCountsBackend {
3131
late CachedValue<Map<String, int>> _thirtyDaysTotals;
3232
var _lastData = (data: <String, int>{}, etag: '');
3333

34+
late CachedValue<Map<String, int>> _trendScores;
35+
var _lastTrendData = (data: <String, int>{}, etag: '');
36+
3437
DownloadCountsBackend(this._db) {
3538
_thirtyDaysTotals = CachedValue(
3639
name: 'thirtyDaysTotalDownloadCounts',
3740
maxAge: Duration(days: 14),
3841
interval: Duration(minutes: 30),
3942
updateFn: _updateThirtyDaysTotals);
43+
_trendScores = CachedValue(
44+
name: 'trendScores',
45+
maxAge: Duration(days: 14),
46+
interval: Duration(minutes: 30),
47+
updateFn: _updateTrendScores);
4048
}
4149

4250
Future<Map<String, int>> _updateThirtyDaysTotals() async {
@@ -74,17 +82,54 @@ class DownloadCountsBackend {
7482
}
7583
}
7684

85+
Future<Map<String, int>> _updateTrendScores() async {
86+
try {
87+
final info = await storageService
88+
.bucket(activeConfiguration.reportsBucketName!)
89+
.infoWithRetry(trendScoreFileName);
90+
91+
if (_lastTrendData.etag == info.etag) {
92+
return _lastTrendData.data;
93+
}
94+
final data = (await storageService
95+
.bucket(activeConfiguration.reportsBucketName!)
96+
.readWithRetry(
97+
trendScoreFileName,
98+
(input) async => await input
99+
.transform(utf8.decoder)
100+
.transform(json.decoder)
101+
.single as Map<String, dynamic>,
102+
))
103+
.cast<String, int>();
104+
_lastTrendData = (data: data, etag: info.etag);
105+
return data;
106+
} on FormatException catch (e, st) {
107+
logger.severe('Error package trend scores:', e, st);
108+
rethrow;
109+
} on DetailedApiRequestError catch (e, st) {
110+
if (e.status != 404) {
111+
logger.severe('Failed to load $trendScoreFileName, error : ', e, st);
112+
}
113+
rethrow;
114+
}
115+
}
116+
77117
Future<void> start() async {
78118
await _thirtyDaysTotals.update();
119+
await _trendScores.update();
79120
}
80121

81122
Future<void> close() async {
82123
await _thirtyDaysTotals.close();
124+
await _trendScores.close();
83125
}
84126

85127
int? lookup30DaysTotalCounts(String package) =>
86128
_thirtyDaysTotals.isAvailable ? _thirtyDaysTotals.value![package] : null;
87129

130+
int? lookupTrendScore(String package) =>
131+
_trendScores.isAvailable ? _trendScores.value![package] : null;
132+
88133
Future<CountData?> lookupDownloadCountData(String pkg) async {
89134
return (await cache.downloadCounts(pkg).get(() async {
90135
final key = _db.emptyKey.append(DownloadCounts, id: pkg);

app/test/service/download_counts/computations_test.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,4 +337,24 @@ void main() {
337337
expect(data, trends);
338338
});
339339
});
340+
341+
testWithProfile('cache package trend scores', fn: () async {
342+
await generateFakeTrendScores({'foo': 3, 'bar': 1, 'baz': 2});
343+
expect(downloadCountsBackend.lookupTrendScore('foo'), isNull);
344+
expect(downloadCountsBackend.lookupTrendScore('bar'), isNull);
345+
expect(downloadCountsBackend.lookupTrendScore('baz'), isNull);
346+
347+
await downloadCountsBackend.start();
348+
expect(downloadCountsBackend.lookupTrendScore('foo'), 3);
349+
expect(downloadCountsBackend.lookupTrendScore('bar'), 1);
350+
expect(downloadCountsBackend.lookupTrendScore('baz'), 2);
351+
expect(downloadCountsBackend.lookupTrendScore('bax'), isNull);
352+
353+
await generateFakeTrendScores({'foo': 9, 'bar': 2, 'baz': 5});
354+
await downloadCountsBackend.start();
355+
expect(downloadCountsBackend.lookupTrendScore('foo'), 9);
356+
expect(downloadCountsBackend.lookupTrendScore('bar'), 2);
357+
expect(downloadCountsBackend.lookupTrendScore('baz'), 5);
358+
expect(downloadCountsBackend.lookupTrendScore('bax'), isNull);
359+
});
340360
}

0 commit comments

Comments
 (0)