1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-26 17:03:12 +03:00

DeviceList: bring save forward if necessary

If save is called with a delay that would want the save to happen
sooner then the save we currently have scheduled, cancel the
current save and schedule a new one for the sooner time.
This commit is contained in:
David Baker
2018-03-08 15:35:35 +00:00
parent 3d1fcc6f83
commit facfcf679d

View File

@@ -92,6 +92,12 @@ export default class DeviceList {
// Promise resolved when device data is saved // Promise resolved when device data is saved
this._savePromise = null; this._savePromise = null;
// Function that resolves the save promise
this._resolveSavePromise = null;
// The time the save is scheduled for
this._savePromiseTime = null;
// The timer used to delay the save
this._saveTimer = null;
} }
/** /**
@@ -159,17 +165,42 @@ export default class DeviceList {
if (!this._dirty) return Promise.resolve(false); if (!this._dirty) return Promise.resolve(false);
if (delay === undefined) delay = 500; if (delay === undefined) delay = 500;
if (this._savePromise === null) { const targetTime = Date.now + delay;
if (this._savePromiseTime && targetTime < this._savePromiseTime) {
// There's a save scheduled but for after we would like: cancel
// it & schedule one for the time we want
clearTimeout(this._saveTimer);
this._saveTimer = null;
this._savePromiseTime = null;
// (but keep the save promise since whatever called save before
// will still want to know when the save is done)
}
let savePromise = this._savePromise;
if (savePromise === null) {
savePromise = new Promise((resolve, reject) => {
this._resolveSavePromise = resolve;
});
this._savePromise = savePromise;
}
if (this._saveTimer === null) {
// Delay saves for a bit so we can aggregate multiple saves that happen // Delay saves for a bit so we can aggregate multiple saves that happen
// in quick succession (eg. when a whole room's devices are marked as known) // in quick succession (eg. when a whole room's devices are marked as known)
this._savePromise = Promise.delay(delay).then(() => { const resolveSavePromise = this._resolveSavePromise;
this._savePromiseTime = targetTime;
this._saveTimer = setTimeout(() => {
console.log('Saving device tracking data at token ' + this._syncToken); console.log('Saving device tracking data at token ' + this._syncToken);
// null out savePromise now (after the delay but before the write), // null out savePromise now (after the delay but before the write),
// otherwise we could return the existing promise when the save has // otherwise we could return the existing promise when the save has
// actually already happened. Likewise for the dirty flag. // actually already happened. Likewise for the dirty flag.
this._savePromiseTime = null;
this._saveTimer = null;
this._savePromise = null; this._savePromise = null;
this._resolveSavePromise = null;
this._dirty = false; this._dirty = false;
return this._cryptoStore.doTxn( this._cryptoStore.doTxn(
'readwrite', [IndexedDBCryptoStore.STORE_DEVICE_DATA], (txn) => { 'readwrite', [IndexedDBCryptoStore.STORE_DEVICE_DATA], (txn) => {
this._cryptoStore.storeEndToEndDeviceData({ this._cryptoStore.storeEndToEndDeviceData({
devices: this._devices, devices: this._devices,
@@ -177,12 +208,12 @@ export default class DeviceList {
syncToken: this._syncToken, syncToken: this._syncToken,
}, txn); }, txn);
}, },
); ).then(() => {
}).then(() => { resolveSavePromise();
return true;
}); });
}, delay);
} }
return this._savePromise; return savePromise;
} }
/** /**