Skip to content

Commit 26e2bce

Browse files
committed
Use new HTTP retry logic when fetching SDK's index.json
1 parent 86434c4 commit 26e2bce

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

app/lib/search/backend.dart

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ void registerSearchIndex(SearchIndex index) =>
8787
class SearchBackend {
8888
final DatastoreDB _db;
8989
final VersionedJsonStorage _snapshotStorage;
90-
final _http = httpRetryClient();
9190

9291
SearchBackend(this._db, Bucket snapshotBucket)
9392
: _snapshotStorage = VersionedJsonStorage(snapshotBucket, 'snapshot/');
@@ -454,11 +453,7 @@ class SearchBackend {
454453
}
455454
}
456455

457-
final rs = await _http.get(uri);
458-
if (rs.statusCode != 200) {
459-
throw Exception('Unexpected status code for $uri: ${rs.statusCode}');
460-
}
461-
final content = rs.body;
456+
final content = await httpGetWithRetry(uri, responseFn: (rs) => rs.body);
462457
await file.parent.create(recursive: true);
463458
await file.writeAsString(content);
464459
return content;
@@ -519,7 +514,6 @@ class SearchBackend {
519514

520515
Future<void> close() async {
521516
_snapshotStorage.close();
522-
_http.close();
523517
}
524518
}
525519

pkg/_pub_shared/lib/utils/http.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'dart:async';
56
import 'dart:io';
67

78
import 'package:http/http.dart' as http;
89
import 'package:http/retry.dart';
10+
import 'package:retry/retry.dart';
911

1012
final _transientStatusCodes = {
1113
// See: https://cloud.google.com/storage/docs/xml-api/reference-status
@@ -35,3 +37,45 @@ http.Client httpRetryClient({
3537
whenError: (e, st) => lenient || e is SocketException,
3638
);
3739
}
40+
41+
/// Creates a HTTP client and executes a GET request to the specified [uri],
42+
/// making sure that the HTTP resources are freed after the [responseFn]
43+
/// callback finishes.
44+
/// The HTTP GET and the [responseFn] callback is retried on the transient
45+
/// network errors.
46+
Future<K> httpGetWithRetry<K>(
47+
Uri uri, {
48+
required FutureOr<K> Function(http.Response response) responseFn,
49+
int maxAttempts = 3,
50+
}) async {
51+
return await retry(
52+
() async {
53+
final client = http.Client();
54+
try {
55+
final rs = await client.get(uri);
56+
if (rs.statusCode == 200) {
57+
return responseFn(rs);
58+
}
59+
throw http.ClientException(
60+
'Unexpected status code for $uri: ${rs.statusCode}.');
61+
} finally {
62+
client.close();
63+
}
64+
},
65+
maxAttempts: maxAttempts,
66+
retryIf: _retryIf,
67+
);
68+
}
69+
70+
bool _retryIf(Exception e) {
71+
if (e is TimeoutException) {
72+
return true; // Timeouts we can retry
73+
}
74+
if (e is IOException) {
75+
return true; // I/O issues are worth retrying
76+
}
77+
if (e is http.ClientException) {
78+
return true; // HTTP issues are worth retrying
79+
}
80+
return false;
81+
}

pkg/_pub_shared/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies:
1313
logging: ^1.2.0
1414
meta: ^1.3.0
1515
pub_semver: ^2.0.0
16+
retry: ^3.1.2
1617
sanitize_html: ^2.1.0
1718
api_builder:
1819

0 commit comments

Comments
 (0)