From 039a3e258bdea9e4bf9c23cc21efc4f42dba5863 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 6 Apr 2017 18:09:12 +0100 Subject: [PATCH] Make indexeddb startup faster Don't needlessly transfer data from the worker to the main script only to immediately transfer it right back again. --- src/store/indexeddb-local-backend.js | 24 +++++++++++++++++++++--- src/store/indexeddb-remote-backend.js | 27 +++++++++------------------ src/store/indexeddb-remote-worker.js | 13 +++++-------- src/store/indexeddb.js | 22 ++++------------------ 4 files changed, 39 insertions(+), 47 deletions(-) diff --git a/src/store/indexeddb-local-backend.js b/src/store/indexeddb-local-backend.js index 5017a4c92f7..d0094e89b5b 100644 --- a/src/store/indexeddb-local-backend.js +++ b/src/store/indexeddb-local-backend.js @@ -136,6 +136,24 @@ LocalIndexedDBStoreBackend.prototype = { }); }, + /** + * Having connected, load initial data from the database and prepare for use + */ + init: function() { + return q.all([ + this._loadAccountData(), + this._loadSyncData(), + ]).then(([accountData, syncData]) => { + this._syncAccumulator.accumulate({ + next_batch: syncData.nextBatch, + rooms: syncData.roomsData, + account_data: { + events: accountData, + }, + }); + }); + }, + /** * Clear the entire database. This should be used when logging out of a client * to prevent mixing data between accounts. @@ -250,7 +268,7 @@ LocalIndexedDBStoreBackend.prototype = { * sync. * @return {Promise} A list of presence events in their raw form. */ - loadUserPresenceEvents: function() { + getUserPresenceEvents: function() { return q.try(() => { const txn = this.db.transaction(["users"], "readonly"); const store = txn.objectStore("users"); @@ -264,7 +282,7 @@ LocalIndexedDBStoreBackend.prototype = { * Load all the account data events from the database. This is not cached. * @return {Promise} A list of raw global account events. */ - loadAccountData: function() { + _loadAccountData: function() { return q.try(() => { const txn = this.db.transaction(["accountData"], "readonly"); const store = txn.objectStore("accountData"); @@ -278,7 +296,7 @@ LocalIndexedDBStoreBackend.prototype = { * Load the sync data from the database. * @return {Promise} An object with "roomsData" and "nextBatch" keys. */ - loadSyncData: function() { + _loadSyncData: function() { return q.try(() => { const txn = this.db.transaction(["sync"], "readonly"); const store = txn.objectStore("sync"); diff --git a/src/store/indexeddb-remote-backend.js b/src/store/indexeddb-remote-backend.js index 89510062f5e..6b27b988296 100644 --- a/src/store/indexeddb-remote-backend.js +++ b/src/store/indexeddb-remote-backend.js @@ -55,6 +55,13 @@ RemoteIndexedDBStoreBackend.prototype = { return this._doCmd('connect'); }, + /** + * Having connected, load initial data from the database and prepare for use + */ + init: function() { + return this._doCmd('init'); + }, + /** * Clear the entire database. This should be used when logging out of a client * to prevent mixing data between accounts. @@ -86,24 +93,8 @@ RemoteIndexedDBStoreBackend.prototype = { * Load all user presence events from the database. This is not cached. * @return {Promise} A list of presence events in their raw form. */ - loadUserPresenceEvents: function() { - return this._doCmd('loadUserPresenceEvents'); - }, - - /** - * Load all the account data events from the database. This is not cached. - * @return {Promise} A list of raw global account events. - */ - loadAccountData: function() { - return this._doCmd('loadAccountData'); - }, - - /** - * Load the sync data from the database. - * @return {Promise} An object with "roomsData" and "nextBatch" keys. - */ - loadSyncData: function() { - return this._doCmd('loadSyncData'); + getUserPresenceEvents: function() { + return this._doCmd('getUserPresenceEvents'); }, _doCmd: function(cmd, args) { diff --git a/src/store/indexeddb-remote-worker.js b/src/store/indexeddb-remote-worker.js index d822ba7c935..0a857f0a9b4 100644 --- a/src/store/indexeddb-remote-worker.js +++ b/src/store/indexeddb-remote-worker.js @@ -45,6 +45,9 @@ class IndexedDbStoreWorker { case 'connect': prom = this.backend.connect(); break; + case 'init': + prom = this.backend.init(); + break; case 'clearDatabase': prom = this.backend.clearDatabase().then((result) => { // This returns special classes which can't be cloned @@ -64,14 +67,8 @@ class IndexedDbStoreWorker { return {}; }); break; - case 'loadUserPresenceEvents': - prom = this.backend.loadUserPresenceEvents(); - break; - case 'loadAccountData': - prom = this.backend.loadAccountData(); - break; - case 'loadSyncData': - prom = this.backend.loadSyncData(); + case 'getUserPresenceEvents': + prom = this.backend.getUserPresenceEvents(); break; } diff --git a/src/store/indexeddb.js b/src/store/indexeddb.js index 34dcdf7190b..a575b915c39 100644 --- a/src/store/indexeddb.js +++ b/src/store/indexeddb.js @@ -111,17 +111,10 @@ IndexedDBStore.prototype.startup = function() { // the web worker to then immediately push it back again without // using it. return this.backend.connect().then(() => { - return q.all([ - this.backend.loadUserPresenceEvents(), - this.backend.loadAccountData(), - this.backend.loadSyncData(), - ]); - }).then((values) => { - const [userPresenceEvents, accountData, syncData] = values; - console.log( - "Loaded data from database: sync from ", syncData.nextBatch, - " -- Reticulating splines...", - ); + return this.backend.init(); + }).then(() => { + return this.backend.getUserPresenceEvents(); + }).then((userPresenceEvents) => { userPresenceEvents.forEach(([userId, rawEvent]) => { const u = new User(userId); if (rawEvent) { @@ -131,13 +124,6 @@ IndexedDBStore.prototype.startup = function() { this.storeUser(u); }); this._syncTs = Date.now(); // pretend we've written so we don't rewrite - return this.setSyncData({ - next_batch: syncData.nextBatch, - rooms: syncData.roomsData, - account_data: { - events: accountData, - }, - }); }); };