diff --git a/src/client.js b/src/client.js index 97f24be77..0b74f3276 100644 --- a/src/client.js +++ b/src/client.js @@ -164,8 +164,6 @@ function MatrixClient(opts) { this.olmVersion = Crypto.getOlmVersion(); } - - this._syncAccumulator = this.store.getSyncAccumulator(); } utils.inherits(MatrixClient, EventEmitter); utils.extend(MatrixClient.prototype, MatrixBaseApis.prototype); @@ -2789,7 +2787,6 @@ MatrixClient.prototype.startClient = function(opts) { opts = Object.assign({}, opts); opts.crypto = this._crypto; - opts.syncAccumulator = this._syncAccumulator; opts.canResetEntireTimeline = (roomId) => { if (!this._canResetTimelineCallback) { return false; diff --git a/src/store/indexeddb.js b/src/store/indexeddb.js index 75c4f73e6..e698d754a 100644 --- a/src/store/indexeddb.js +++ b/src/store/indexeddb.js @@ -288,17 +288,27 @@ IndexedDBStore.prototype.startup = function() { }); this._syncTs = Date.now(); // pretend we've written so we don't rewrite this.setSyncToken(syncData.nextBatch); - this._setSyncData(syncData.nextBatch, syncData.roomsData, accountData); + this.setSyncData({ + next_batch: syncData.nextBatch, + rooms: syncData.roomsData, + account_data: { + events: accountData, + }, + }); }); }; /** - * Return the accumulator which will have the initial /sync data when startup() - * is called. - * @return {SyncAccumulator} + * @return {Promise} Resolves with a sync response to restore the + * client state to where it was at the last save, or null if there + * is no saved sync data. */ -IndexedDBStore.prototype.getSyncAccumulator = function() { - return this._syncAccumulator; +IndexedDBStore.prototype.getSavedSync = function() { + const data = this._syncAccumulator.getJSON(); + if (!data.nextBatch) return q(null); + // We must deep copy the stored data so that the /sync processing code doesn't + // corrupt the internal state of the sync accumulator (it adds non-clonable keys) + return q(utils.deepCopy(data)); }; /** @@ -327,14 +337,8 @@ IndexedDBStore.prototype.save = function() { return q(); }; -IndexedDBStore.prototype._setSyncData = function(nextBatch, roomsData, accountData) { - this._syncAccumulator.accumulate({ - next_batch: nextBatch, - rooms: roomsData, - account_data: { - events: accountData, - }, - }); +IndexedDBStore.prototype.setSyncData = function(syncData) { + this._syncAccumulator.accumulate(syncData); }; IndexedDBStore.prototype._syncToDatabase = function() { diff --git a/src/store/memory.js b/src/store/memory.js index 6d5ff309e..d6c4bbbb0 100644 --- a/src/store/memory.js +++ b/src/store/memory.js @@ -277,19 +277,16 @@ module.exports.MatrixInMemoryStore.prototype = { return this.accountData[eventType]; }, + /** + * setSyncData does nothing as there is no backing data store. + */ + setSyncData: function(syncData) {}, + /** * Save does nothing as there is no backing data store. */ save: function() {}, - /** - * Returns nothing as this store does not accumulate /sync data. - * @return {?SyncAccumulator} null - */ - getSyncAccumulator: function() { - return null; - }, - /** * Startup does nothing as this store doesn't require starting up. * @return {Promise} An immediately resolved promise. diff --git a/src/store/stub.js b/src/store/stub.js index fb716dd75..2b64a2a2a 100644 --- a/src/store/stub.js +++ b/src/store/stub.js @@ -182,19 +182,16 @@ StubStore.prototype = { }, + /** + * setSyncData does nothing as there is no backing data store. + */ + setSyncData: function(syncData) {}, + /** * Save does nothing as there is no backing data store. */ save: function() {}, - /** - * Returns nothing as this store does not accumulate /sync data. - * @return {?SyncAccumulator} null - */ - getSyncAccumulator: function() { - return null; - }, - /** * Startup does nothing. * @return {Promise} An immediately resolved promise. diff --git a/src/sync.js b/src/sync.js index 4ca1aacf5..78f00607b 100644 --- a/src/sync.js +++ b/src/sync.js @@ -60,7 +60,6 @@ function debuglog() { * @param {MatrixClient} client The matrix client instance to use. * @param {Object} opts Config options * @param {module:crypto=} opts.crypto Crypto manager - * @param {SyncAccumulator=} opts.syncAccumulator An accumulator which will be * kept up-to-date. If one is supplied, the response to getJSON() will be used * initially. * @param {Function=} opts.canResetEntireTimeline A function which is called @@ -542,34 +541,35 @@ SyncApi.prototype._sync = function(syncOptions) { } let isCachedResponse = false; - if (self.opts.syncAccumulator && !syncOptions.hasSyncedBefore) { - let data = self.opts.syncAccumulator.getJSON(); + + let syncPromise; + if (!syncOptions.hasSyncedBefore) { // Don't do an HTTP hit to /sync. Instead, load up the persisted /sync data, // if there is data there. - if (data.nextBatch) { + syncPromise = client.store.getSavedSync(); + } else { + syncPromise = q(null); + } + + syncPromise.then((savedSync) => { + if (savedSync) { debuglog("sync(): not doing HTTP hit, instead returning stored /sync data"); - // We must deep copy the stored data so that the /sync processing code doesn't - // corrupt the internal state of the sync accumulator (it adds non-clonable keys) - data = utils.deepCopy(data); - this._currentSyncRequest = q.resolve({ - next_batch: data.nextBatch, - rooms: data.roomsData, - account_data: { - events: data.accountData, - }, - }); isCachedResponse = true; + return { + next_batch: savedSync.nextBatch, + rooms: savedSync.roomsData, + account_data: { + events: savedSync.accountData, + }, + }; + } else { + //debuglog('Starting sync since=' + syncToken); + this._currentSyncRequest = client._http.authedRequest( + undefined, "GET", "/sync", qps, undefined, clientSideTimeoutMs, + ); + return this._currentSyncRequest; } - } - - if (!isCachedResponse) { - //debuglog('Starting sync since=' + syncToken); - this._currentSyncRequest = client._http.authedRequest( - undefined, "GET", "/sync", qps, undefined, clientSideTimeoutMs, - ); - } - - this._currentSyncRequest.done(function(data) { + }).done(function(data) { //debuglog('Completed sync, next_batch=' + data.next_batch); // set the sync token NOW *before* processing the events. We do this so @@ -585,11 +585,9 @@ SyncApi.prototype._sync = function(syncOptions) { console.error("Caught /sync error", e.stack || e); } - // If there's an accumulator then the first HTTP response is actually the - // accumulated data. We don't want to accumulate the same thing twice, so - // only accumulate if this isn't a cached response. - if (self.opts.syncAccumulator && !isCachedResponse) { - self.opts.syncAccumulator.accumulate(data); + // Don't give the store back its own cached data + if (!isCachedResponse) { + client.store.setSyncData(data); } // emit synced events