mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-21 09:05:10 -07:00
[PictureLoader] Seed per-host allowances on demand and skip hosts in 429 backoff
The quota reset re-filled every host's remaining allowance to a full MAX_REQUESTS_PER_SEC as soon as the queue had a request for it. A server that was just rate limited could therefore be hammered again at full speed immediately after (or even during) recovery. Only seed a host's allowance the first time it is dispatched in the current second, seeded from its reduced sustained quota, and skip hosts still inside their 429 backoff window entirely. This makes the pacing commit's burst-free behavior hold per host too, instead of just smoothing the global aggregate.
This commit is contained in:
parent
64b3b7e0b4
commit
5a6db206ce
3 changed files with 23 additions and 7 deletions
|
|
@ -138,6 +138,9 @@ QNetworkReply *CardPictureLoaderWorker::makeRequest(const QUrl &url, CardPicture
|
|||
void CardPictureLoaderWorker::resetRequestQuota()
|
||||
{
|
||||
requestQuota = MAX_REQUESTS_PER_SEC;
|
||||
// Allowances are seeded per host on demand in processSingleRequest(), so a
|
||||
// rate-limited host never gets a fresh full quota mid-second.
|
||||
hostQuotaRemaining.clear();
|
||||
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
for (auto it = hostRequestQuota.begin(); it != hostRequestQuota.end(); ++it) {
|
||||
|
|
@ -146,11 +149,6 @@ void CardPictureLoaderWorker::resetRequestQuota()
|
|||
}
|
||||
}
|
||||
|
||||
for (const auto &request : requestLoadQueue) {
|
||||
const QString host = request.first.host();
|
||||
hostQuotaRemaining.insert(host, hostRequestQuota.value(host, MAX_REQUESTS_PER_SEC));
|
||||
}
|
||||
|
||||
processQueuedRequests();
|
||||
}
|
||||
|
||||
|
|
@ -184,10 +182,20 @@ void CardPictureLoaderWorker::dispatchQueuedRequest()
|
|||
|
||||
bool CardPictureLoaderWorker::processSingleRequest()
|
||||
{
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
for (int i = 0; i < requestLoadQueue.size(); ++i) {
|
||||
const auto &request = requestLoadQueue.at(i);
|
||||
QString host = request.first.host();
|
||||
int allowance = hostQuotaRemaining.value(host, MAX_REQUESTS_PER_SEC);
|
||||
const QString host = request.first.host();
|
||||
// Don't dispatch requests to a host that is currently in its 429 backoff.
|
||||
if (CardPictureLoaderWorkerWork::rateLimiter().isRateLimited(host, now)) {
|
||||
continue;
|
||||
}
|
||||
// Seed the allowance only now, so a host that was rate limited last second
|
||||
// doesn't get a fresh full quota the moment it is queried mid-second.
|
||||
if (!hostQuotaRemaining.contains(host)) {
|
||||
hostQuotaRemaining.insert(host, hostRequestQuota.value(host, MAX_REQUESTS_PER_SEC));
|
||||
}
|
||||
int allowance = hostQuotaRemaining.value(host);
|
||||
if (allowance > 0) {
|
||||
hostQuotaRemaining.insert(host, allowance - 1);
|
||||
makeRequest(request.first, request.second);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,11 @@ static const QStringList MD5_BLACKLIST = {
|
|||
"fbc7d763c08771c260b39e2115414eeb" // Current card back hash
|
||||
};
|
||||
|
||||
ServerRateLimiter &CardPictureLoaderWorkerWork::rateLimiter()
|
||||
{
|
||||
return s_rateLimiter;
|
||||
}
|
||||
|
||||
CardPictureLoaderWorkerWork::CardPictureLoaderWorkerWork(const CardPictureLoaderWorker *worker, const ExactCard &toLoad)
|
||||
: QObject(nullptr), cardToDownload(CardPictureToLoad(toLoad)),
|
||||
picDownload(SettingsCache::instance().downloads().getPicDownload())
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ public:
|
|||
|
||||
CardPictureToLoad cardToDownload; ///< The card and associated URLs to try downloading
|
||||
|
||||
/** @brief Shared per-server 429 backoff state. */
|
||||
static ServerRateLimiter &rateLimiter();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Handles a finished network reply for the card image.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue