autoretry with a randomly increasing delay

This commit is contained in:
tophf 2021-06-29 19:29:58 +03:00
parent c3a99ff6a0
commit 2fcd37d708

View File

@ -11,6 +11,7 @@ const syncMan = (() => {
const SYNC_DELAY = 1; // minutes const SYNC_DELAY = 1; // minutes
const SYNC_INTERVAL = 30; // minutes const SYNC_INTERVAL = 30; // minutes
const SYNC_LOCK_RETRIES = 10; // number of retries before the error is reported for scheduled sync
const STATES = Object.freeze({ const STATES = Object.freeze({
connected: 'connected', connected: 'connected',
connecting: 'connecting', connecting: 'connecting',
@ -26,9 +27,9 @@ const syncMan = (() => {
currentDriveName: null, currentDriveName: null,
errorMessage: null, errorMessage: null,
login: false, login: false,
lockRetries: 0,
}; };
let lastError = null; let lastError = null;
let lastInterval = Math.random();
let ctrl; let ctrl;
let currentDrive; let currentDrive;
/** @type {Promise|boolean} will be `true` to avoid wasting a microtask tick on each `await` */ /** @type {Promise|boolean} will be `true` to avoid wasting a microtask tick on each `await` */
@ -43,12 +44,9 @@ const syncMan = (() => {
chrome.alarms.onAlarm.addListener(async ({name}) => { chrome.alarms.onAlarm.addListener(async ({name}) => {
if (name === 'syncNow') { if (name === 'syncNow') {
await syncMan.syncNow(); await syncMan.syncNow({isScheduled: true});
/* We want to fire the alarm once per SYNC_INTERVAL at a random point within the range, const retrying = status.lockRetries / SYNC_LOCK_RETRIES * Math.random();
* so the new delay includes the leftover portion from the last range. */ schedule(SYNC_DELAY + SYNC_INTERVAL * (retrying || 1));
const r = Math.random();
schedule(SYNC_DELAY + SYNC_INTERVAL * (1 - lastInterval + r));
lastInterval = r;
} }
}); });
@ -145,7 +143,7 @@ const syncMan = (() => {
emitStatusChange(); emitStatusChange();
}, },
async syncNow() { async syncNow({isScheduled} = {}) {
if (ready.then) await ready; if (ready.then) await ready;
if (!currentDrive || !status.login) { if (!currentDrive || !status.login) {
console.warn('cannot sync when disconnected'); console.warn('cannot sync when disconnected');
@ -158,11 +156,16 @@ const syncMan = (() => {
} catch (err) { } catch (err) {
status.errorMessage = err.message; status.errorMessage = err.message;
lastError = err; lastError = err;
if (isScheduled &&
err.code === 409 &&
++status.lockRetries <= SYNC_LOCK_RETRIES) {
return;
}
if (isGrantError(err)) { if (isGrantError(err)) {
status.login = false; status.login = false;
} }
} }
status.lockRetries = 0;
emitStatusChange(); emitStatusChange();
}, },
}; };
@ -253,7 +256,7 @@ const syncMan = (() => {
function schedule(delay = SYNC_DELAY) { function schedule(delay = SYNC_DELAY) {
chrome.alarms.create('syncNow', { chrome.alarms.create('syncNow', {
delayInMinutes: delay, delayInMinutes: delay, // fractional values are supported
}); });
} }