Skip to content

Commit c87f614

Browse files
committed
Refactor: select task versions based on the cached package data from API endpoint.
1 parent 704b8b9 commit c87f614

File tree

2 files changed

+84
-70
lines changed

2 files changed

+84
-70
lines changed

app/lib/package/backend.dart

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -970,21 +970,34 @@ class PackageBackend {
970970
/// getting it from cache if available.
971971
///
972972
/// This returns gzipped UTF-8 encoded JSON.
973-
Future<List<int>> listVersionsGzCachedBytes(String package) async {
974-
final body = await cache.packageDataGz(package).get(() async {
975-
final data = await listVersions(package);
976-
final raw = jsonUtf8Encoder.convert(data.toJson());
977-
return gzip.encode(raw);
978-
});
979-
return body!;
973+
Future<List<int>> listVersionsGzCachedBytes(
974+
String package, {
975+
bool refreshVersionsCache = false,
976+
}) async {
977+
final entry = cache.packageDataGz(package);
978+
final cached = refreshVersionsCache ? null : await entry.get();
979+
if (cached != null) {
980+
return cached;
981+
}
982+
final data = await listVersions(package);
983+
final raw = jsonUtf8Encoder.convert(data.toJson());
984+
final zipped = gzip.encode(raw);
985+
await entry.set(zipped);
986+
return zipped;
980987
}
981988

982989
/// Returns the known versions of [package] (via [listVersions]),
983990
/// getting it from the cache if available.
984991
///
985992
/// The available versions are sorted by their semantic version number (ascending).
986-
Future<api.PackageData> listVersionsCached(String package) async {
987-
final data = await listVersionsGzCachedBytes(package);
993+
Future<api.PackageData> listVersionsCached(
994+
String package, {
995+
bool refreshVersionsCache = false,
996+
}) async {
997+
final data = await listVersionsGzCachedBytes(
998+
package,
999+
refreshVersionsCache: refreshVersionsCache,
1000+
);
9881001
return api.PackageData.fromJson(
9891002
utf8JsonDecoder.convert(gzip.decode(data)) as Map<String, dynamic>,
9901003
);
@@ -2455,6 +2468,7 @@ class _VersionTransactionDataAcccess {
24552468
() => taskBackend.trackPackage(
24562469
package,
24572470
updateDependents: taskUpdateDependents,
2471+
refreshVersionsCache: true,
24582472
),
24592473
),
24602474
if (!skipExport)

app/lib/task/backend.dart

Lines changed: 61 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'dart:convert';
33
import 'dart:io';
44
import 'dart:typed_data';
55

6+
import 'package:_pub_shared/data/package_api.dart' as package_api;
67
import 'package:_pub_shared/data/task_api.dart' as api;
78
import 'package:_pub_shared/data/task_payload.dart';
89
import 'package:_pub_shared/worker/limits.dart';
@@ -363,44 +364,31 @@ class TaskBackend {
363364
Future<void> trackPackage(
364365
String packageName, {
365366
bool updateDependents = false,
367+
bool refreshVersionsCache = false,
366368
}) async {
367369
var lastVersionCreated = initialTimestamp;
368370
String? latestVersion;
369-
final changed = await withRetryTransaction(_db, (tx) async {
370-
// Lookup Package and PackageVersion in the same transaction.
371-
final packageFuture = tx.packages.lookupOrNull(packageName);
372-
final packageVersionsFuture = tx.versions.listVersionsOfPackage(
371+
late package_api.PackageData data;
372+
try {
373+
data = await packageBackend.listVersionsCached(
373374
packageName,
375+
refreshVersionsCache: refreshVersionsCache,
374376
);
375-
final stateFuture = tx.tasks.lookupOrNull(packageName);
376-
// Ensure we await all futures!
377-
await Future.wait([packageFuture, packageVersionsFuture, stateFuture]);
378-
final state = await stateFuture;
379-
final package = await packageFuture;
380-
final packageVersions = await packageVersionsFuture;
381-
382-
if (package == null) {
383-
return false; // assume package was deleted!
384-
}
385-
latestVersion = package.latestVersion;
377+
} on NotFoundException catch (_) {
378+
// If package is not visible, we should remove it!
379+
await _db.tasks.deleteAllStates(packageName);
380+
return;
381+
}
382+
final versions = _versionsToTrack(
383+
data,
384+
).map((v) => v.canonicalizedVersion).toList();
385+
final changed = await withRetryTransaction(_db, (tx) async {
386+
final state = await tx.tasks.lookupOrNull(packageName);
387+
latestVersion = data.latest.version;
386388

387389
// Update the timestamp for when the last version was published.
388390
// This is used if we need to update dependents.
389-
lastVersionCreated = packageVersions.map((pv) => pv.created!).max;
390-
391-
// If package is not visible, we should remove it!
392-
if (package.isNotVisible) {
393-
await tx.tasks.deleteAllStates(
394-
packageName,
395-
currentRuntimeKey: state?.key,
396-
);
397-
return true;
398-
}
399-
400-
// Determined the set of versions to track
401-
final versions = _versionsToTrack(package, packageVersions).map(
402-
(v) => v.canonicalizedVersion, // add extra sanity!
403-
);
391+
lastVersionCreated = data.versions.map((pv) => pv.published!).max;
404392

405393
// Ensure we have PackageState entity
406394
if (state == null) {
@@ -1202,34 +1190,49 @@ PackageVersionStateInfo _authorizeWorkerCallback(
12021190
/// * Latest preview release (if newer than latest stable release);
12031191
/// * Latest prerelease (if newer than latest preview release);
12041192
/// * 5 latest major versions (if any).
1205-
List<Version> _versionsToTrack(
1206-
Package package,
1207-
List<PackageVersion> packageVersions,
1208-
) {
1209-
final visibleVersions = packageVersions
1193+
List<Version> _versionsToTrack(package_api.PackageData data) {
1194+
final visibleVersions = data.versions
12101195
// Ignore retracted versions
1211-
.where((pv) => !pv.isRetracted)
1212-
// Ignore moderated versions
1213-
.where((pv) => pv.isVisible)
1214-
.map((pv) => pv.semanticVersion)
1196+
.where((pv) => !(pv.retracted ?? false))
1197+
.map((pv) => Version.parse(pv.version))
12151198
.toSet();
12161199
final visibleStableVersions =
12171200
visibleVersions
12181201
// Ignore prerelease versions
12191202
.where((v) => !v.isPreRelease)
12201203
.toList()
12211204
..sort((a, b) => -a.compareTo(b));
1205+
1206+
final latestVersion = Version.parse(data.latest.version);
1207+
1208+
// consider preview version if it is newer than current latest release
1209+
final stableAfterLatest = visibleStableVersions
1210+
.where((a) => latestVersion.compareTo(a) < 0)
1211+
.toList();
1212+
final latestPreview = stableAfterLatest.isEmpty
1213+
? null
1214+
: stableAfterLatest.reduce((a, b) => a.compareTo(b) < 0 ? b : a);
1215+
1216+
// consider prerelease version if it is newer than current latest release
1217+
final prereleaseAfterLatest = visibleVersions
1218+
.where((a) => a.isPreRelease)
1219+
.where((a) => latestVersion.compareTo(a) < 0)
1220+
.toList();
1221+
final latestPrerelease = prereleaseAfterLatest.isEmpty
1222+
? null
1223+
: prereleaseAfterLatest.reduce((a, b) => a.compareTo(b) < 0 ? b : a);
12221224
return {
12231225
// Always analyze latest version (may be non-stable if package has only prerelease versions).
1224-
package.latestSemanticVersion,
1226+
latestVersion,
12251227

1226-
// Consider latest two stable versions to keep previously analyzed results on new package publishing.
1227-
...visibleStableVersions.take(2),
1228+
// Consider latest two older stable versions to keep previously analyzed results on new package publishing.
1229+
...visibleStableVersions
1230+
.where((a) => a.compareTo(latestVersion) <= 0)
1231+
.take(2),
12281232

1229-
// Only consider prerelease and preview versions, if they are newer than
1230-
// the current stable release.
1231-
if (package.showPrereleaseVersion) package.latestPrereleaseSemanticVersion,
1232-
if (package.showPreviewVersion) package.latestPreviewSemanticVersion,
1233+
// Consider the latest prerelease and preview version.
1234+
if (latestPrerelease != null) latestPrerelease,
1235+
if (latestPreview != null) latestPreview,
12331236

12341237
// Consider 5 latest major versions, if any:
12351238
...visibleStableVersions
@@ -1374,6 +1377,18 @@ final class _TaskDataAccess {
13741377
}
13751378
}
13761379

1380+
Future<void> deleteAllStates(String name) async {
1381+
await withRetryTransaction(_db, (tx) async {
1382+
// also delete earlier runtime versions
1383+
for (final rv in acceptedRuntimeVersions) {
1384+
final s = await lookupOrNull(name, runtimeVersion: rv);
1385+
if (s != null) {
1386+
tx.delete(s.key);
1387+
}
1388+
}
1389+
});
1390+
}
1391+
13771392
/// Returns whether the entry has been updated.
13781393
Future<bool> updateDependencyChanged(
13791394
String package,
@@ -1435,21 +1450,6 @@ class _TaskTransactionDataAcccess {
14351450
return await _tx.lookupOrNull<PackageState>(key);
14361451
}
14371452

1438-
Future<void> deleteAllStates(String name, {Key? currentRuntimeKey}) async {
1439-
if (currentRuntimeKey != null) {
1440-
_tx.delete(currentRuntimeKey);
1441-
}
1442-
// also delete earlier runtime versions
1443-
for (final rv in acceptedRuntimeVersions.where(
1444-
(rv) => rv != runtimeVersion,
1445-
)) {
1446-
final s = await lookupOrNull(name, runtimeVersion: rv);
1447-
if (s != null) {
1448-
_tx.delete(s.key);
1449-
}
1450-
}
1451-
}
1452-
14531453
Future<void> insert(PackageState state) async {
14541454
_tx.insert(state);
14551455
}

0 commit comments

Comments
 (0)