From d37242d594b82d998a6bbf105e712b3c64522e33 Mon Sep 17 00:00:00 2001
From: "nweiz@google.com" <nweiz@google.com>
Date: Thu, 24 Jul 2014 23:14:19 +0000
Subject: [PATCH] Limit pub to 16 concurrent HTTP requests.

R=alanknight@google.com
BUG=20058

Review URL: https://codereview.chromium.org//415373002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge@38561 260f80e4-7a28-3924-810f-c04153c831b5
---
 lib/src/http.dart  | 20 ++++++++++++++------
 test/test_pub.dart |  6 +++---
 2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/lib/src/http.dart b/lib/src/http.dart
index 24dbacbe..4fe118eb 100644
--- a/lib/src/http.dart
+++ b/lib/src/http.dart
@@ -10,6 +10,7 @@ import 'dart:convert';
 import 'dart:io';
 
 import 'package:http/http.dart' as http;
+import 'package:http_throttle/http_throttle.dart';
 
 import 'io.dart';
 import 'log.dart' as log;
@@ -38,13 +39,13 @@ final PUB_API_HEADERS = const {'Accept': 'application/vnd.pub.v2+json'};
 /// This also adds a 30-second timeout to every request. This can be configured
 /// on a per-request basis by setting the 'Pub-Request-Timeout' header to the
 /// desired number of milliseconds, or to "None" to disable the timeout.
-class PubHttpClient extends http.BaseClient {
+class _PubHttpClient extends http.BaseClient {
   final _requestStopwatches = new Map<http.BaseRequest, Stopwatch>();
 
-  http.Client inner;
+  http.Client _inner;
 
-  PubHttpClient([http.Client inner])
-      : this.inner = inner == null ? new http.Client() : inner;
+  _PubHttpClient([http.Client inner])
+      : this._inner = inner == null ? new http.Client() : inner;
 
   Future<http.StreamedResponse> send(http.BaseRequest request) {
     _requestStopwatches[request] = new Stopwatch()..start();
@@ -67,7 +68,7 @@ class PubHttpClient extends http.BaseClient {
       timeoutLength = int.parse(timeoutString);
     }
 
-    var future = inner.send(request).then((streamedResponse) {
+    var future = _inner.send(request).then((streamedResponse) {
       _logResponse(streamedResponse);
 
       var status = streamedResponse.statusCode;
@@ -191,8 +192,15 @@ class PubHttpClient extends http.BaseClient {
   }
 }
 
+/// The [_PubHttpClient] wrapped by [httpClient].
+final _pubClient = new _PubHttpClient();
+
 /// The HTTP client to use for all HTTP requests.
-final httpClient = new PubHttpClient();
+final httpClient = new ThrottleClient(16, _pubClient);
+
+/// The underlying HTTP client wrapped by [httpClient].
+http.Client get innerHttpClient => _pubClient._inner;
+set innerHttpClient(http.Client client) => _pubClient._inner = client;
 
 /// Handles a successful JSON-formatted response from pub.dartlang.org.
 ///
diff --git a/test/test_pub.dart b/test/test_pub.dart
index 1bbf3071..6729e0d3 100644
--- a/test/test_pub.dart
+++ b/test/test_pub.dart
@@ -835,10 +835,10 @@ Iterable<String> pkg, Map<String, String> hosted}) {
 /// Note that this will only affect HTTP requests made via http.dart in the
 /// parent process.
 void useMockClient(MockClient client) {
-  var oldInnerClient = httpClient.inner;
-  httpClient.inner = client;
+  var oldInnerClient = innerHttpClient;
+  innerHttpClient = client;
   currentSchedule.onComplete.schedule(() {
-    httpClient.inner = oldInnerClient;
+    innerHttpClient = oldInnerClient;
   }, 'de-activating the mock client');
 }
 
-- 
GitLab