Skip to content

Commit bd33b48

Browse files
authored
Use download counts for ranking + fake download counts in tests. (#8340)
1 parent 465e59b commit bd33b48

13 files changed

+89
-29
lines changed

app/lib/fake/backend/fake_popularity.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
import 'dart:math' as math;
66

7+
import 'package:clock/clock.dart';
8+
79
import '../../package/models.dart';
10+
import '../../service/download_counts/backend.dart';
811
import '../../shared/datastore.dart';
912
import '../../shared/popularity_storage.dart';
1013

@@ -23,3 +26,20 @@ Future<void> generateFakePopularityValues() async {
2326
// ignore: invalid_use_of_visible_for_testing_member
2427
popularityStorage.updateValues(values, invalid: false);
2528
}
29+
30+
/// Scans the datastore for packages and generates download count values with a
31+
/// deterministic random seed.
32+
Future<void> generateFakeDownloadCounts() async {
33+
final query = dbService.query<Package>();
34+
await for (final p in query.run()) {
35+
final r = math.Random(p.name.hashCode.abs());
36+
final count = (math.min(p.likes * p.likes, 50) + r.nextInt(50));
37+
await downloadCountsBackend.updateDownloadCounts(
38+
p.name!,
39+
{
40+
p.latestVersion!: count,
41+
},
42+
clock.now(),
43+
);
44+
}
45+
}

app/lib/fake/server/fake_analyzer_service.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class FakeAnalyzerService {
3838
storage: _storage,
3939
cloudCompute: _cloudCompute,
4040
fn: () async {
41+
await generateFakeDownloadCounts();
4142
await generateFakePopularityValues();
4243

4344
final handler = wrapHandler(_logger, analyzerServiceHandler);

app/lib/fake/server/fake_default_service.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class FakePubServer {
4848
await watchForResourceChanges();
4949
}
5050

51+
await generateFakeDownloadCounts();
5152
await generateFakePopularityValues();
5253
await generateFakeTopicValues();
5354
await nameTracker.startTracking();

app/lib/fake/server/fake_search_service.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class FakeSearchService {
5454
});
5555
_logger.info('running on port $port');
5656

57+
await generateFakeDownloadCounts();
5758
await generateFakePopularityValues();
5859
// ignore: invalid_use_of_visible_for_testing_member
5960
await indexUpdater.updateAllPackages();

app/lib/search/backend.dart

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,7 @@ class SearchBackend {
175175
if (!claim.valid) {
176176
return;
177177
}
178-
snapshot.updateLikeScores();
179-
snapshot.updatePopularityScores();
178+
snapshot.updateAllScores();
180179

181180
// first complete snapshot, uploading it
182181
await _snapshotStorage.uploadDataAsJsonMap(snapshot.toJson());
@@ -205,11 +204,8 @@ class SearchBackend {
205204
futures.clear();
206205

207206
if (claim.valid && lastUploadedSnapshotTimestamp != snapshot.updated) {
208-
// Updates the normalized like score across all the packages.
209-
snapshot.updateLikeScores();
210-
// Updates all popularity values to the currently cached one, otherwise
211-
// only updated package would have been on their new values.
212-
snapshot.updatePopularityScores();
207+
// Updates the normalized scores across all the packages.
208+
snapshot.updateAllScores();
213209

214210
await _snapshotStorage.uploadDataAsJsonMap(snapshot.toJson());
215211
lastUploadedSnapshotTimestamp = snapshot.updated!;

app/lib/search/mem_index.dart

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,14 @@ class InMemoryPackageIndex {
8888
);
8989
_apiSymbolIndex = TokenIndex(apiDocPageKeys, apiDocPageValues);
9090

91+
// update download scores only if they were not set (should happen on old runtime's snapshot and local tests)
92+
if (_documents.any((e) => e.downloadScore == null)) {
93+
_documents.updateDownloadScores();
94+
}
95+
9196
// update like scores only if they were not set (should happen only in local tests)
92-
if (_documentsByName.values.any((e) => e.likeScore == null)) {
93-
_documentsByName.values.updateLikeScores();
97+
if (_documents.any((e) => e.likeScore == null)) {
98+
_documents.updateLikeScores();
9499
}
95100
_updateOverallScores();
96101
_lastUpdated = clock.now().toUtc();
@@ -263,7 +268,7 @@ class InMemoryPackageIndex {
263268
/// Update the overall score both on [PackageDocument] and in the [_adjustedOverallScores] map.
264269
void _updateOverallScores() {
265270
_adjustedOverallScores = _documents.map((doc) {
266-
final downloadScore = doc.popularityScore ?? 0.0;
271+
final downloadScore = doc.downloadScore ?? doc.popularityScore ?? 0.0;
267272
final likeScore = doc.likeScore ?? 0.0;
268273
final popularity = (downloadScore + likeScore) / 2;
269274
final points = doc.grantedPoints / math.max(1, doc.maxPoints);

app/lib/search/models.dart

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,22 @@ class SearchSnapshot {
3333
documents!.remove(packageName);
3434
}
3535

36-
/// Updates the PackageDocument.likeScore for each package in the snapshot.
37-
/// The score is normalized into the range of [0.0 - 1.0] using the
38-
/// ordered list of packages by like counts (same like count gets the same score).
39-
void updateLikeScores() {
36+
/// Updates the [PackageDocument] instance's scores for each package in the snapshot.
37+
/// Sets `downloadScore`, `likeScore` and `popularityScore` fields, normalized into the
38+
/// range of [0.0 - 1.0] using the ordered list of their specific counts.
39+
void updateAllScores() {
40+
/// Updates the PackageDocument.downloadScore for each package in the snapshot.
41+
/// The score is normalized into the range of [0.0 - 1.0] using the
42+
/// ordered list of packages by download counts (same download count gets the same score).
43+
documents!.values.updateDownloadScores();
44+
45+
/// Updates the PackageDocument.likeScore for each package in the snapshot.
46+
/// The score is normalized into the range of [0.0 - 1.0] using the
47+
/// ordered list of packages by like counts (same like count gets the same score).
4048
documents!.values.updateLikeScores();
41-
}
4249

43-
/// Updates all popularity values to the currently cached one, otherwise
44-
/// only updated package would have been on their new values.
45-
void updatePopularityScores() {
50+
/// Updates all popularity values to the currently cached one, otherwise
51+
/// only updated package would have been on their new values.
4652
for (final d in documents!.values) {
4753
if (popularityStorage.isInvalid) {
4854
d.popularityScore = d.likeScore;
@@ -56,6 +62,20 @@ class SearchSnapshot {
5662
}
5763

5864
extension UpdateLikesExt on Iterable<PackageDocument> {
65+
/// Updates the PackageDocument.downloadScore for each package in the snapshot.
66+
/// The score is normalized into the range of [0.0 - 1.0] using the
67+
/// ordered list of packages by download counts (same download count gets the same score).
68+
void updateDownloadScores() {
69+
final list = sorted((a, b) => a.downloadCount.compareTo(b.downloadCount));
70+
for (var i = 0; i < list.length; i++) {
71+
if (i > 0 && list[i - 1].downloadCount == list[i].downloadCount) {
72+
list[i].downloadScore = list[i - 1].downloadScore;
73+
} else {
74+
list[i].downloadScore = (i + 1) / list.length;
75+
}
76+
}
77+
}
78+
5979
/// Updates the PackageDocument.likeScore for each package in the snapshot.
6080
/// The score is normalized into the range of [0.0 - 1.0] using the
6181
/// ordered list of packages by like counts (same like count gets the same score).

app/lib/search/search_service.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ class PackageDocument {
7474
final List<String> tags;
7575

7676
final int downloadCount;
77+
78+
/// The normalized score between [0.0-1.0] (1.0 being the most downloaded package).
79+
double? downloadScore;
80+
7781
final int likeCount;
7882

7983
/// The normalized score between [0.0-1.0] (1.0 being the most liked package).
@@ -107,6 +111,7 @@ class PackageDocument {
107111
this.readme = '',
108112
List<String>? tags,
109113
int? downloadCount,
114+
this.downloadScore,
110115
int? likeCount,
111116
this.likeScore,
112117
this.popularityScore,

app/lib/search/search_service.g.dart

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/test/frontend/handlers/listing_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ void main() {
9191
(i) => TestPackage(
9292
name: 'pkg$i', versions: [TestVersion(version: '1.0.0')])),
9393
), fn: () async {
94-
final present = ['pkg5', 'pkg7', 'pkg11', 'pkg13', 'pkg14'];
95-
final absent = ['pkg0', 'pkg2', 'pkg3', 'pkg4', 'pkg6', 'pkg9', 'pkg10'];
94+
final present = ['pkg1', 'pkg4', 'pkg5', 'pkg12'];
95+
final absent = ['pkg0', 'pkg3', 'pkg6', 'pkg9', 'pkg10'];
9696
await expectHtmlResponse(
9797
await issueGet('/packages?page=2'),
9898
present: present.map((name) => '/packages/$name').toList(),

0 commit comments

Comments
 (0)