fix: serialize interval waits so uploads stagger correctly

Previously all jobs read the same lastStartTime simultaneously,
causing them all to start at once. Now uses a per-hoster promise
chain to ensure each job waits its turn.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Administrator 2026-03-11 03:56:04 +01:00
parent e6bad780ee
commit 1af7f8a94d

View File

@ -35,6 +35,7 @@ class UploadManager extends EventEmitter {
this.cancelledJobIds = new Set(); this.cancelledJobIds = new Set();
this.sessionBytes = 0; this.sessionBytes = 0;
this.lastStartTime = {}; // hoster -> timestamp of last upload start this.lastStartTime = {}; // hoster -> timestamp of last upload start
this.intervalLocks = {}; // hoster -> Promise chain for serialized interval waits
this.globalThrottle = null; this.globalThrottle = null;
} }
@ -544,14 +545,20 @@ class UploadManager extends EventEmitter {
}); });
} }
async _waitForInterval(hoster, intervalMs, signal) { _waitForInterval(hoster, intervalMs, signal) {
const now = Date.now(); // Serialize interval waits per hoster so concurrent jobs queue up properly
const last = this.lastStartTime[hoster] || 0; const prev = this.intervalLocks[hoster] || Promise.resolve();
const elapsed = now - last; const next = prev.then(async () => {
if (elapsed < intervalMs) { const now = Date.now();
await this._sleep(intervalMs - elapsed, signal); const last = this.lastStartTime[hoster] || 0;
} const elapsed = now - last;
this.lastStartTime[hoster] = Date.now(); if (elapsed < intervalMs) {
await this._sleep(intervalMs - elapsed, signal);
}
this.lastStartTime[hoster] = Date.now();
});
this.intervalLocks[hoster] = next.catch(() => {});
return next;
} }
cancelJobs(jobIds) { cancelJobs(jobIds) {