Skip to content

Commit 65645b3

Browse files
committed
Trigger post-update events for Package updates.
1 parent 59af9a0 commit 65645b3

9 files changed

+84
-46
lines changed

app/lib/admin/actions/merge_moderated_package_into_existing.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Fails if that package has no existing Package entity.
6262
tx.insert(p!);
6363
tx.delete(mpKey);
6464
});
65-
await purgePackageCache(packageName);
65+
await triggerPackagePostUpdates(packageName).future;
6666

6767
return {
6868
'package': packageName,

app/lib/admin/actions/moderate_package.dart

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44

55
import '../../admin/backend.dart';
66
import '../../admin/models.dart';
7-
import '../../package/api_export/api_exporter.dart';
87
import '../../package/backend.dart';
98
import '../../package/models.dart';
9+
import '../../scorecard/backend.dart';
1010
import '../../shared/datastore.dart';
11-
import '../../task/backend.dart';
1211
import 'actions.dart';
1312

1413
final moderatePackage = AdminAction(
@@ -108,11 +107,7 @@ Future<Map<String, dynamic>> adminMarkPackageVisibility(
108107
return pkg;
109108
});
110109

111-
// make sure visibility cache is updated immediately
112-
await purgePackageCache(package);
113-
114-
// sync exported API(s)
115-
await apiExporter.synchronizePackage(package, forceDelete: true);
110+
await triggerPackagePostUpdates(package, exportForceDelete: true).future;
116111

117112
// retract or re-populate public archive files
118113
await packageBackend.tarballStorage.updatePublicArchiveBucket(
@@ -121,8 +116,7 @@ Future<Map<String, dynamic>> adminMarkPackageVisibility(
121116
deleteIfOlder: Duration.zero,
122117
);
123118

124-
await taskBackend.trackPackage(package);
125-
await purgePackageCache(package);
119+
await purgeScorecardData(package, p2!.latestVersion!, isLatest: true);
126120
}
127121

128122
return {

app/lib/admin/actions/moderate_package_versions.dart

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
import 'package:_pub_shared/utils/sdk_version_cache.dart';
66
import 'package:clock/clock.dart';
77

8-
import '../../package/api_export/api_exporter.dart';
98
import '../../package/backend.dart';
109
import '../../package/models.dart';
1110
import '../../scorecard/backend.dart';
1211
import '../../shared/datastore.dart';
1312
import '../../shared/versions.dart';
14-
import '../../task/backend.dart';
1513

1614
import '../backend.dart';
1715
import '../models.dart';
@@ -144,11 +142,7 @@ Future<Map<String, dynamic>> adminMarkPackageVersionVisibility(
144142
return v;
145143
});
146144

147-
// make sure visibility cache is updated immediately
148-
await purgePackageCache(package);
149-
150-
// sync exported API(s)
151-
await apiExporter.synchronizePackage(package, forceDelete: true);
145+
await triggerPackagePostUpdates(package, exportForceDelete: true).future;
152146

153147
// retract or re-populate public archive files
154148
await packageBackend.tarballStorage.updatePublicArchiveBucket(
@@ -157,8 +151,6 @@ Future<Map<String, dynamic>> adminMarkPackageVersionVisibility(
157151
deleteIfOlder: Duration.zero,
158152
);
159153

160-
await taskBackend.trackPackage(package);
161-
await purgePackageCache(package);
162154
await purgeScorecardData(package, version, isLatest: true);
163155
}
164156

app/lib/admin/actions/package_version_retraction.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ value of `set-retracted`, which should either be `true` or `false`.
8888
'isRetracted': pv.isRetracted,
8989
};
9090
});
91-
await purgePackageCache(packageName);
91+
triggerPackagePostUpdates(packageName);
9292

9393
return {
9494
'before': before,

app/lib/admin/actions/publisher_package_remove.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ If the publisher has no members, the package will end up without uploaders.
5959
),
6060
);
6161
});
62-
await purgePackageCache(packageName);
62+
triggerPackagePostUpdates(packageName,
63+
skipTask: true, skipVersionsExport: true);
6364
await purgePublisherCache(publisherId: currentPublisherId);
6465
return {
6566
'previousPublisher': currentPublisherId,

app/lib/admin/backend.dart

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import '../account/models.dart';
2323
import '../admin/models.dart';
2424
import '../audit/models.dart';
2525
import '../package/backend.dart'
26-
show checkPackageVersionParams, packageBackend, purgePackageCache;
26+
show checkPackageVersionParams, packageBackend, triggerPackagePostUpdates;
2727
import '../package/models.dart';
2828
import '../publisher/models.dart';
2929
import '../scorecard/backend.dart';
@@ -32,7 +32,6 @@ import '../shared/configuration.dart';
3232
import '../shared/datastore.dart';
3333
import '../shared/exceptions.dart';
3434
import '../shared/versions.dart';
35-
import '../task/backend.dart';
3635
import 'actions/actions.dart' show AdminAction;
3736
import 'tools/delete_all_staging.dart';
3837
import 'tools/list_tools.dart';
@@ -400,7 +399,7 @@ class AdminBackend {
400399
await _db
401400
.deleteWithQuery(_db.query<PackageVersion>(ancestorKey: packageKey));
402401

403-
await purgePackageCache(packageName);
402+
triggerPackagePostUpdates(packageName);
404403

405404
_logger.info('Package "$packageName" got successfully removed.');
406405
return (
@@ -448,7 +447,7 @@ class AdminBackend {
448447
caller, tx, p, pv, isRetracted);
449448
}
450449
});
451-
await purgePackageCache(packageName);
450+
triggerPackagePostUpdates(packageName);
452451
}
453452
}
454453

@@ -517,10 +516,8 @@ class AdminBackend {
517516
tx.insert(package);
518517
});
519518

520-
await purgePackageCache(packageName);
521519
await purgeScorecardData(packageName, version, isLatest: true);
522-
// trigger (eventual) re-analysis
523-
await taskBackend.trackPackage(packageName);
520+
triggerPackagePostUpdates(packageName);
524521
return (
525522
deletedPackageVersions: deletedPackageVersions,
526523
deletedPackageVersionInfos: deletedPackageVersionInfos.deleted,

app/lib/admin/tools/package_publisher.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ Future<String> executeSetPackagePublisher(List<String> args) async {
4242
tx.insert(pkg);
4343
});
4444
await purgePublisherCache(publisherId: publisherId);
45-
await purgePackageCache(packageName);
45+
triggerPackagePostUpdates(packageName,
46+
skipTask: true, skipVersionsExport: true);
4647
if (currentPublisherId != null) {
4748
await purgePublisherCache(publisherId: currentPublisherId);
4849
}

app/lib/package/backend.dart

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,11 @@ class PackageBackend {
381381
return true;
382382
});
383383
if (updated) {
384-
await purgePackageCache(package);
384+
triggerPackagePostUpdates(
385+
package,
386+
skipTask: true,
387+
skipExport: true,
388+
);
385389
}
386390
return updated;
387391
}
@@ -480,9 +484,7 @@ class PackageBackend {
480484
options: optionsChanges,
481485
));
482486
});
483-
await purgePackageCache(package);
484-
await taskBackend.trackPackage(package);
485-
await apiExporter.synchronizePackage(package);
487+
triggerPackagePostUpdates(package, skipVersionsExport: true);
486488
}
487489

488490
/// Updates [options] on [package]/[version], assuming the current user
@@ -520,10 +522,9 @@ class PackageBackend {
520522
authenticatedUser, tx, p, pv, options.isRetracted!);
521523
}
522524
});
523-
await purgePackageCache(package);
524525
await purgeScorecardData(package, version,
525526
isLatest: pkg.latestVersion == version);
526-
await apiExporter.synchronizePackage(package);
527+
triggerPackagePostUpdates(package);
527528
}
528529

529530
/// Verifies an update to the credential-less publishing settings and
@@ -780,15 +781,18 @@ class PackageBackend {
780781
return _asPackagePublisherInfo(package);
781782
});
782783
await purgePublisherCache(publisherId: request.publisherId);
783-
await purgePackageCache(packageName);
784784

785785
if (email != null) {
786786
await emailBackend.trySendOutgoingEmail(email!);
787787
}
788788
if (currentPublisherId != null) {
789789
await purgePublisherCache(publisherId: currentPublisherId);
790790
}
791-
await apiExporter.synchronizePackage(packageName);
791+
triggerPackagePostUpdates(
792+
packageName,
793+
skipTask: true,
794+
skipVersionsExport: true,
795+
);
792796
return rs;
793797
}
794798

@@ -1299,7 +1303,7 @@ class PackageBackend {
12991303
sw.reset();
13001304

13011305
_logger.info('Invalidating cache for package ${newVersion.package}.');
1302-
await purgePackageCache(newVersion.package);
1306+
triggerPackagePostUpdates(newVersion.package, taskUpdateDependents: true);
13031307

13041308
// Let's not block the upload response on these post-upload tasks.
13051309
// The operations should either be non-critical, or should be retried
@@ -1324,12 +1328,10 @@ class PackageBackend {
13241328
await Future.wait([
13251329
if (activeConfiguration.isPublishedEmailNotificationEnabled)
13261330
emailBackend.trySendOutgoingEmail(outgoingEmail),
1327-
taskBackend.trackPackage(newVersion.package, updateDependents: true),
1328-
apiExporter.synchronizePackage(newVersion.package),
13291331
apiExporter.synchronizeAllPackagesAtomFeed(),
1332+
tarballStorage.updateContentDispositionOnPublicBucket(
1333+
newVersion.package, newVersion.version!),
13301334
]);
1331-
await tarballStorage.updateContentDispositionOnPublicBucket(
1332-
newVersion.package, newVersion.version!);
13331335
} catch (e, st) {
13341336
final v = newVersion.qualifiedVersionKey;
13351337
_logger.severe('Error post-processing package upload $v', e, st);
@@ -1581,7 +1583,7 @@ class PackageBackend {
15811583
package: packageName,
15821584
));
15831585
});
1584-
await purgePackageCache(packageName);
1586+
triggerPackagePostUpdates(packageName, skipTask: true, skipExport: true);
15851587
}
15861588

15871589
Future<void> _validatePackageUploader(
@@ -1657,7 +1659,7 @@ class PackageBackend {
16571659
uploaderUser: uploader,
16581660
));
16591661
});
1660-
await purgePackageCache(packageName);
1662+
triggerPackagePostUpdates(packageName, skipTask: true, skipExport: true);
16611663
return api.SuccessMessage(
16621664
success: api.Message(
16631665
message:
@@ -2096,3 +2098,49 @@ class _VersionTransactionDataAcccess {
20962098
return await _tx.query<PackageVersion>(pkgKey).run().toList();
20972099
}
20982100
}
2101+
2102+
/// Triggers post-update event processing after a [Package] object is part of
2103+
/// a transaction.
2104+
///
2105+
/// Returns a record with an optionally awaitable [Future] in case the caller needs
2106+
/// wait the updates before yielding its response.
2107+
({Future future}) triggerPackagePostUpdates(
2108+
String package, {
2109+
/// Skip trigger a new analysis on the package.
2110+
bool skipTask = false,
2111+
2112+
/// Skip triggering a new export to the CDN bucket.
2113+
bool skipExport = false,
2114+
2115+
/// Skip only the version-related exports to the CDN bucket, keeps the
2116+
/// package-related operations.
2117+
/// TODO: implement this in API exporter.
2118+
bool skipVersionsExport = false,
2119+
2120+
/// Pass the force-deletion flag to the package export operation.
2121+
bool exportForceDelete = false,
2122+
2123+
/// Pass the update-dependents flag to the task update operation.
2124+
bool taskUpdateDependents = false,
2125+
}) {
2126+
Future add(Future Function() fn) {
2127+
return asyncQueue.addAsyncFn(fn).future;
2128+
}
2129+
2130+
final futures = [
2131+
add(() => purgePackageCache(package)),
2132+
if (!skipTask)
2133+
add(() => taskBackend.trackPackage(
2134+
package,
2135+
updateDependents: taskUpdateDependents,
2136+
)),
2137+
if (!skipExport)
2138+
add(() => apiExporter.synchronizePackage(
2139+
package,
2140+
forceDelete: exportForceDelete,
2141+
// TODO: implement and use [skipVersionsExport]
2142+
)),
2143+
];
2144+
2145+
return (future: Future.wait(futures));
2146+
}

app/lib/service/async_queue/async_queue.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,14 @@ class AsyncQueue {
4444

4545
AsyncQueue() : _zone = Zone.current;
4646

47-
void addAsyncFn(AsyncFn fn) {
47+
({Future future}) addAsyncFn(AsyncFn fn) {
4848
if (_closed) {
4949
throw StateError('AsyncQueue is closed, task was not accepted.');
5050
}
51-
_queue.add(_Task(fn, StackTrace.current));
51+
final task = _Task(fn, StackTrace.current);
52+
_queue.add(task);
5253
_triggerProcessing();
54+
return (future: task.completer.future);
5355
}
5456

5557
void _triggerProcessing() {
@@ -61,10 +63,12 @@ class AsyncQueue {
6163
final first = _queue.removeFirst();
6264
try {
6365
await first.fn();
66+
first.completer.complete();
6467
} catch (e, st) {
6568
final trace = Chain([Trace.from(first.origin), Trace.from(st)]).terse;
6669
stderr.writeln('Error executing off-request function: $e\n$trace');
6770
_logger.severe('Error executing off-request function.', e, trace);
71+
first.completer.completeError(e, st);
6872
}
6973
}
7074

@@ -80,6 +84,7 @@ class AsyncQueue {
8084
class _Task {
8185
final AsyncFn fn;
8286
final StackTrace origin;
87+
final completer = Completer();
8388

8489
_Task(this.fn, this.origin);
8590
}

0 commit comments

Comments
 (0)