@@ -3,6 +3,7 @@ import 'dart:convert';
33import 'dart:io' ;
44import 'dart:typed_data' ;
55
6+ import 'package:_pub_shared/data/package_api.dart' as package_api;
67import 'package:_pub_shared/data/task_api.dart' as api;
78import 'package:_pub_shared/data/task_payload.dart' ;
89import '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