Throttle HTTP requests made to the auth server

Making thousands of HTTP requests simultaneously inevitably results in some
failing or the server being overwhelmed, so limit how many can be made at once
(currently to the arbitrary cap of 5) and enqueue any further requests.
This commit is contained in:
Thomas Goyne 2018-03-15 16:08:48 -07:00
parent 10480c1afe
commit 635d49e09a
2 changed files with 38 additions and 3 deletions

View File

@ -7,7 +7,7 @@ X.Y.Z Release notes
* Added an optional user as argument to `Realm.automaticSyncConfiguration` (#1708).
### Bug fixes
* None.
* [Sync] Avoid hammering the ROS authentication service when large numbers of Realms are opened at once.
### Internal
* None.

View File

@ -36,8 +36,43 @@ function checkTypes(args, types) {
}
}
/* global fetch */
const performFetch = typeof fetch === 'undefined' ? node_require('node-fetch') : fetch;
// Perform a HTTP request, enqueuing it if too many requests are already in
// progress to avoid hammering the server.
const performFetch = (function() {
const doFetch = typeof fetch === 'undefined' ? node_require('node-fetch') : fetch;
const queue = [];
let count = 0;
const maxCount = 5;
const next = () => {
if (count >= maxCount) {
return;
}
const req = queue.shift();
if (!req) {
return;
}
const [url, options, resolve, reject] = req;
++count;
// node doesn't support Promise.prototype.finally until 10
doFetch(url, options)
.then(response => {
--count;
next();
resolve(response);
})
.catch(error => {
--count;
next();
reject(error);
});
};
return (url, options) => {
return new Promise((resolve, reject) => {
queue.push([url, options, resolve, reject]);
next();
});
};
})();
const url_parse = require('url-parse');