Skip to content

Commit 407d965

Browse files
committed
Use TaskAborted exception to indicate that the current task is no longer expected to complete.
1 parent 9071b4c commit 407d965

File tree

4 files changed

+44
-6
lines changed

4 files changed

+44
-6
lines changed

app/lib/shared/exceptions.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ class NotAcceptableException extends ResponseException {
5151
: super._(406, 'NotAcceptable', message);
5252
}
5353

54+
/// Thrown when the underlying analysis task has been aborted.
55+
class TaskAbortedException extends ResponseException {
56+
TaskAbortedException(String message) : super._(400, 'TaskAborted', message);
57+
}
58+
5459
/// Thrown when request input is invalid, bad payload, wrong querystring, etc.
5560
class InvalidInputException extends ResponseException {
5661
InvalidInputException._(String message)

app/lib/task/backend.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -686,13 +686,14 @@ class TaskBackend {
686686
final key = PackageState.createKey(_db, runtimeVersion, package);
687687
final state = await tx.lookupOrNull<PackageState>(key);
688688
if (state == null || state.versions![version] == null) {
689-
throw NotFoundException.resource('$package/$version');
689+
throw TaskAbortedException(
690+
'$package/$version is no longer selected for analysis.');
690691
}
691692
final versionState = state.versions![version]!;
692693

693694
// Check the secret token
694695
if (!versionState.isAuthorized(_extractBearerToken(request))) {
695-
throw AuthenticationException.authenticationRequired();
696+
throw TaskAbortedException('Secret token is no longer accepted.');
696697
}
697698
assert(versionState.scheduled != initialTimestamp);
698699
assert(versionState.instance != null);

pkg/pub_worker/lib/src/analyze.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,12 @@ Future<void> analyze(Payload payload) async {
9292
'analyze.',
9393
);
9494
}
95+
} on TaskAbortedException catch (e, st) {
96+
_log.warning(
97+
'failed to upload ${payload.package} / ${p.version}', e, st);
9598
} catch (e, st) {
9699
_log.shout(
97-
'failed to process ${payload.package} / ${p.version}',
98-
e,
99-
st,
100-
);
100+
'failed to process ${payload.package} / ${p.version}', e, st);
101101
}
102102
}
103103
} finally {

pkg/pub_worker/lib/src/upload.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'dart:async';
6+
import 'dart:convert';
67
import 'dart:io';
78

89
import 'package:_pub_shared/data/package_api.dart' show UploadInfo;
@@ -40,6 +41,15 @@ Future<void> upload(
4041
));
4142
final res = await Response.fromStream(await client.send(req));
4243

44+
// Special case `TaskAborted` response code, it means that the analysis
45+
// is no longer selected or the secret token timed out / was replaced
46+
// (it may need a different analysis round).
47+
if (res.statusCode == 400 &&
48+
_extractExceptionCode(res) == 'TaskAborted') {
49+
_log.warning(
50+
'Task aborted, failed to upload: $filename, status = ${res.statusCode}');
51+
throw TaskAbortedException(res.body);
52+
}
4353
if (400 <= res.statusCode && res.statusCode < 500) {
4454
_log.shout('Failed to upload: $filename, status = ${res.statusCode}');
4555
throw UploadException(
@@ -80,3 +90,25 @@ final class UploadException implements Exception {
8090
final class IntermittentUploadException extends UploadException {
8191
IntermittentUploadException(String message) : super(message);
8292
}
93+
94+
final class TaskAbortedException extends UploadException {
95+
TaskAbortedException(String message) : super(message);
96+
}
97+
98+
String? _extractExceptionCode(Response res) {
99+
try {
100+
final map = json.decode(res.body);
101+
if (map is! Map) {
102+
return null;
103+
}
104+
final error = map['error'];
105+
if (error is! Map) {
106+
return null;
107+
}
108+
final code = error['code'];
109+
return code?.toString();
110+
} on FormatException catch (_) {
111+
// ignore
112+
}
113+
return null;
114+
}

0 commit comments

Comments
 (0)