From 561879dc6b39a0f8b81ec60f1b5e35d2ecba0c74 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 25 Sep 2020 16:42:41 +0200 Subject: [PATCH] open storage transactions synchronously this (almost) makes it work in some browsers that otherwise have throw a TransactionInactiveError on the first operation you try to do on a store. --- src/matrix/DeviceMessageHandler.js | 4 ++-- src/matrix/Session.js | 12 ++++++------ src/matrix/Sync.js | 12 ++++++------ src/matrix/e2ee/Account.js | 4 ++-- src/matrix/e2ee/DeviceTracker.js | 10 +++++----- src/matrix/e2ee/RoomEncryption.js | 10 +++++----- src/matrix/e2ee/megolm/Encryption.js | 2 +- src/matrix/e2ee/olm/Decryption.js | 2 +- src/matrix/e2ee/olm/Encryption.js | 6 +++--- src/matrix/room/Room.js | 14 +++++++------- src/matrix/room/RoomSummary.js | 2 +- src/matrix/room/members/load.js | 4 ++-- src/matrix/room/sending/SendQueue.js | 4 ++-- .../room/timeline/persistence/TimelineReader.js | 4 ++-- src/matrix/ssss/index.js | 2 +- src/matrix/storage/idb/Storage.js | 4 ++-- 16 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/matrix/DeviceMessageHandler.js b/src/matrix/DeviceMessageHandler.js index 854c901b..e0904133 100644 --- a/src/matrix/DeviceMessageHandler.js +++ b/src/matrix/DeviceMessageHandler.js @@ -80,7 +80,7 @@ export class DeviceMessageHandler { if (!this._olmDecryption) { return; } - const readTxn = await this._storage.readTxn([this._storage.storeNames.session]); + const readTxn = this._storage.readTxn([this._storage.storeNames.session]); const pendingEvents = await this._getPendingEvents(readTxn); if (pendingEvents.length === 0) { return; @@ -91,7 +91,7 @@ export class DeviceMessageHandler { for (const err of decryptChanges.errors) { console.warn("decryption failed for event", err, err.event); } - const txn = await this._storage.readWriteTxn([ + const txn = this._storage.readWriteTxn([ // both to remove the pending events and to modify the olm account this._storage.storeNames.session, this._storage.storeNames.olmSessions, diff --git a/src/matrix/Session.js b/src/matrix/Session.js index ef535fc7..dbb95c24 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -164,13 +164,13 @@ export class Session { } const key = await ssssKeyFromCredential(type, credential, this._storage, this._cryptoDriver, this._olm); // and create session backup, which needs to read from accountData - const readTxn = await this._storage.readTxn([ + const readTxn = this._storage.readTxn([ this._storage.storeNames.accountData, ]); await this._createSessionBackup(key, readTxn); // only after having read a secret, write the key // as we only find out if it was good if the MAC verification succeeds - const writeTxn = await this._storage.readWriteTxn([ + const writeTxn = this._storage.readWriteTxn([ this._storage.storeNames.session, ]); try { @@ -217,7 +217,7 @@ export class Session { await this._e2eeAccount.uploadKeys(this._storage); await this._deviceMessageHandler.decryptPending(this.rooms); - const txn = await this._storage.readTxn([ + const txn = this._storage.readTxn([ this._storage.storeNames.session, this._storage.storeNames.accountData, ]); @@ -231,7 +231,7 @@ export class Session { } async load() { - const txn = await this._storage.readTxn([ + const txn = this._storage.readTxn([ this._storage.storeNames.session, this._storage.storeNames.roomSummary, this._storage.storeNames.roomMembers, @@ -276,7 +276,7 @@ export class Session { async start(lastVersionResponse) { if (lastVersionResponse) { // store /versions response - const txn = await this._storage.readWriteTxn([ + const txn = this._storage.readWriteTxn([ this._storage.storeNames.session ]); txn.session.set("serverVersions", lastVersionResponse); @@ -284,7 +284,7 @@ export class Session { await txn.complete(); } - const opsTxn = await this._storage.readWriteTxn([ + const opsTxn = this._storage.readWriteTxn([ this._storage.storeNames.operations ]); const operations = await opsTxn.operations.getAll(); diff --git a/src/matrix/Sync.js b/src/matrix/Sync.js index 14655b8e..2edc91f2 100644 --- a/src/matrix/Sync.js +++ b/src/matrix/Sync.js @@ -184,7 +184,7 @@ export class Sync { const roomStates = this._parseRoomsResponse(response.rooms, isInitialSync); await this._prepareRooms(roomStates); let sessionChanges; - const syncTxn = await this._openSyncTxn(); + const syncTxn = this._openSyncTxn(); try { await Promise.all(roomStates.map(async rs => { console.log(` * applying sync response to room ${rs.room.id} ...`); @@ -221,24 +221,24 @@ export class Sync { }; } - async _openPrepareSyncTxn() { + _openPrepareSyncTxn() { const storeNames = this._storage.storeNames; - return await this._storage.readTxn([ + return this._storage.readTxn([ storeNames.inboundGroupSessions, ]); } async _prepareRooms(roomStates) { - const prepareTxn = await this._openPrepareSyncTxn(); + const prepareTxn = this._openPrepareSyncTxn(); await Promise.all(roomStates.map(async rs => { rs.preparation = await rs.room.prepareSync(rs.roomResponse, rs.membership, prepareTxn); })); await Promise.all(roomStates.map(rs => rs.room.afterPrepareSync(rs.preparation))); } - async _openSyncTxn() { + _openSyncTxn() { const storeNames = this._storage.storeNames; - return await this._storage.readWriteTxn([ + return this._storage.readWriteTxn([ storeNames.session, storeNames.roomSummary, storeNames.roomState, diff --git a/src/matrix/e2ee/Account.js b/src/matrix/e2ee/Account.js index c0cfd8de..7b4a5b0d 100644 --- a/src/matrix/e2ee/Account.js +++ b/src/matrix/e2ee/Account.js @@ -45,7 +45,7 @@ export class Account { } const pickledAccount = account.pickle(pickleKey); const areDeviceKeysUploaded = false; - const txn = await storage.readWriteTxn([ + const txn = storage.readWriteTxn([ storage.storeNames.session ]); try { @@ -212,7 +212,7 @@ export class Account { } async _updateSessionStorage(storage, callback) { - const txn = await storage.readWriteTxn([ + const txn = storage.readWriteTxn([ storage.storeNames.session ]); try { diff --git a/src/matrix/e2ee/DeviceTracker.js b/src/matrix/e2ee/DeviceTracker.js index cc3a4215..bf6f1403 100644 --- a/src/matrix/e2ee/DeviceTracker.js +++ b/src/matrix/e2ee/DeviceTracker.js @@ -68,7 +68,7 @@ export class DeviceTracker { } const memberList = await room.loadMemberList(); try { - const txn = await this._storage.readWriteTxn([ + const txn = this._storage.readWriteTxn([ this._storage.storeNames.roomSummary, this._storage.storeNames.userIdentities, ]); @@ -149,7 +149,7 @@ export class DeviceTracker { }).response(); const verifiedKeysPerUser = this._filterVerifiedDeviceKeys(deviceKeyResponse["device_keys"]); - const txn = await this._storage.readWriteTxn([ + const txn = this._storage.readWriteTxn([ this._storage.storeNames.userIdentities, this._storage.storeNames.deviceIdentities, ]); @@ -252,7 +252,7 @@ export class DeviceTracker { * @return {[type]} [description] */ async devicesForTrackedRoom(roomId, hsApi) { - const txn = await this._storage.readTxn([ + const txn = this._storage.readTxn([ this._storage.storeNames.roomMembers, this._storage.storeNames.userIdentities, ]); @@ -268,7 +268,7 @@ export class DeviceTracker { } async devicesForRoomMembers(roomId, userIds, hsApi) { - const txn = await this._storage.readTxn([ + const txn = this._storage.readTxn([ this._storage.storeNames.userIdentities, ]); return await this._devicesForUserIds(roomId, userIds, txn, hsApi); @@ -298,7 +298,7 @@ export class DeviceTracker { queriedDevices = await this._queryKeys(outdatedIdentities.map(i => i.userId), hsApi); } - const deviceTxn = await this._storage.readTxn([ + const deviceTxn = this._storage.readTxn([ this._storage.storeNames.deviceIdentities, ]); const devicesPerUser = await Promise.all(upToDateIdentities.map(identity => { diff --git a/src/matrix/e2ee/RoomEncryption.js b/src/matrix/e2ee/RoomEncryption.js index 94af64d1..6063a06c 100644 --- a/src/matrix/e2ee/RoomEncryption.js +++ b/src/matrix/e2ee/RoomEncryption.js @@ -183,7 +183,7 @@ export class RoomEncryption { console.warn("Got session key back from backup with different sender key, ignoring", {session, senderKey}); return; } - const txn = await this._storage.readWriteTxn([this._storage.storeNames.inboundGroupSessions]); + const txn = this._storage.readWriteTxn([this._storage.storeNames.inboundGroupSessions]); let roomKey; try { roomKey = await this._megolmDecryption.addRoomKeyFromBackup( @@ -273,7 +273,7 @@ export class RoomEncryption { const userIds = Array.from(devices.reduce((set, device) => set.add(device.userId), new Set())); // store operation for room key share, in case we don't finish here - const writeOpTxn = await this._storage.readWriteTxn([this._storage.storeNames.operations]); + const writeOpTxn = this._storage.readWriteTxn([this._storage.storeNames.operations]); let operationId; try { operationId = this._writeRoomKeyShareOperation(roomKeyMessage, userIds, writeOpTxn); @@ -290,7 +290,7 @@ export class RoomEncryption { await this._sendRoomKey(roomKeyMessage, devices, hsApi); // remove the operation - const removeOpTxn = await this._storage.readWriteTxn([this._storage.storeNames.operations]); + const removeOpTxn = this._storage.readWriteTxn([this._storage.storeNames.operations]); try { removeOpTxn.operations.remove(operationId); } catch (err) { @@ -329,7 +329,7 @@ export class RoomEncryption { this._isFlushingRoomKeyShares = true; try { if (!operations) { - const txn = await this._storage.readTxn([this._storage.storeNames.operations]); + const txn = this._storage.readTxn([this._storage.storeNames.operations]); operations = await txn.operations.getAllByTypeAndScope("share_room_key", this._room.id); } for (const operation of operations) { @@ -339,7 +339,7 @@ export class RoomEncryption { } const devices = await this._deviceTracker.devicesForRoomMembers(this._room.id, operation.userIds, hsApi); await this._sendRoomKey(operation.roomKeyMessage, devices, hsApi); - const removeTxn = await this._storage.readWriteTxn([this._storage.storeNames.operations]); + const removeTxn = this._storage.readWriteTxn([this._storage.storeNames.operations]); try { removeTxn.operations.remove(operation.id); } catch (err) { diff --git a/src/matrix/e2ee/megolm/Encryption.js b/src/matrix/e2ee/megolm/Encryption.js index cb0dddf8..a0769ba1 100644 --- a/src/matrix/e2ee/megolm/Encryption.js +++ b/src/matrix/e2ee/megolm/Encryption.js @@ -54,7 +54,7 @@ export class Encryption { async encrypt(roomId, type, content, encryptionParams) { let session = new this._olm.OutboundGroupSession(); try { - const txn = await this._storage.readWriteTxn([ + const txn = this._storage.readWriteTxn([ this._storage.storeNames.inboundGroupSessions, this._storage.storeNames.outboundGroupSessions, ]); diff --git a/src/matrix/e2ee/olm/Decryption.js b/src/matrix/e2ee/olm/Decryption.js index a193e016..7c4ef7e6 100644 --- a/src/matrix/e2ee/olm/Decryption.js +++ b/src/matrix/e2ee/olm/Decryption.js @@ -67,7 +67,7 @@ export class Decryption { return this._senderKeyLock.takeLock(senderKey); })); try { - const readSessionsTxn = await this._storage.readTxn([this._storage.storeNames.olmSessions]); + const readSessionsTxn = this._storage.readTxn([this._storage.storeNames.olmSessions]); // decrypt events for different sender keys in parallel const senderKeyOperations = await Promise.all(Array.from(eventsPerSenderKey.entries()).map(([senderKey, events]) => { return this._decryptAllForSenderKey(senderKey, events, timestamp, readSessionsTxn); diff --git a/src/matrix/e2ee/olm/Encryption.js b/src/matrix/e2ee/olm/Encryption.js index 919acc45..ff5f1a8f 100644 --- a/src/matrix/e2ee/olm/Encryption.js +++ b/src/matrix/e2ee/olm/Encryption.js @@ -98,7 +98,7 @@ export class Encryption { } async _findExistingSessions(devices) { - const txn = await this._storage.readTxn([this._storage.storeNames.olmSessions]); + const txn = this._storage.readTxn([this._storage.storeNames.olmSessions]); const sessionIdsForDevice = await Promise.all(devices.map(async device => { return await txn.olmSessions.getSessionIds(device.curve25519Key); })); @@ -213,7 +213,7 @@ export class Encryption { } async _loadSessions(encryptionTargets) { - const txn = await this._storage.readTxn([this._storage.storeNames.olmSessions]); + const txn = this._storage.readTxn([this._storage.storeNames.olmSessions]); // given we run loading in parallel, there might still be some // storage requests that will finish later once one has failed. // those should not allocate a session anymore. @@ -239,7 +239,7 @@ export class Encryption { } async _storeSessions(encryptionTargets, timestamp) { - const txn = await this._storage.readWriteTxn([this._storage.storeNames.olmSessions]); + const txn = this._storage.readWriteTxn([this._storage.storeNames.olmSessions]); try { for (const target of encryptionTargets) { const sessionEntry = createSessionEntry( diff --git a/src/matrix/room/Room.js b/src/matrix/room/Room.js index 369836ee..f12da45b 100644 --- a/src/matrix/room/Room.js +++ b/src/matrix/room/Room.js @@ -82,7 +82,7 @@ export class Room extends EventEmitter { let retryEntries; if (retryEventIds) { retryEntries = []; - txn = await this._storage.readTxn(stores); + txn = this._storage.readTxn(stores); for (const eventId of retryEventIds) { const storageEntry = await txn.timelineEvents.getByEventId(this._roomId, eventId); if (storageEntry) { @@ -99,7 +99,7 @@ export class Room extends EventEmitter { // check we have not already decrypted the most recent event in the room // otherwise we know that the messages for this room key will not update the room summary if (!sinceEventKey || !sinceEventKey.equals(this._syncWriter.lastMessageKey)) { - txn = await this._storage.readTxn(stores.concat(this._storage.storeNames.timelineFragments)); + txn = this._storage.readTxn(stores.concat(this._storage.storeNames.timelineFragments)); const candidateEntries = await this._readRetryDecryptCandidateEntries(sinceEventKey, txn); retryEntries = this._roomEncryption.findAndCacheEntriesForRoomKey(roomKey, candidateEntries); } @@ -138,7 +138,7 @@ export class Room extends EventEmitter { _decryptEntries(source, entries, inboundSessionTxn = null) { const request = new DecryptionRequest(async r => { if (!inboundSessionTxn) { - inboundSessionTxn = await this._storage.readTxn([this._storage.storeNames.inboundGroupSessions]); + inboundSessionTxn = this._storage.readTxn([this._storage.storeNames.inboundGroupSessions]); } if (r.cancelled) return; const events = entries.filter(entry => { @@ -155,7 +155,7 @@ export class Room extends EventEmitter { // read to fetch devices if timeline is open stores.push(this._storage.storeNames.deviceIdentities); } - const writeTxn = await this._storage.readWriteTxn(stores); + const writeTxn = this._storage.readWriteTxn(stores); let decryption; try { decryption = await changes.write(writeTxn); @@ -387,7 +387,7 @@ export class Room extends EventEmitter { } }).response(); - const txn = await this._storage.readWriteTxn([ + const txn = this._storage.readWriteTxn([ this._storage.storeNames.pendingEvents, this._storage.storeNames.timelineEvents, this._storage.storeNames.timelineFragments, @@ -490,7 +490,7 @@ export class Room extends EventEmitter { async _getLastEventId() { const lastKey = this._syncWriter.lastMessageKey; if (lastKey) { - const txn = await this._storage.readTxn([ + const txn = this._storage.readTxn([ this._storage.storeNames.timelineEvents, ]); const eventEntry = await txn.timelineEvents.get(this._roomId, lastKey); @@ -511,7 +511,7 @@ export class Room extends EventEmitter { async clearUnread() { if (this.isUnread || this.notificationCount) { - const txn = await this._storage.readWriteTxn([ + const txn = this._storage.readWriteTxn([ this._storage.storeNames.roomSummary, ]); let data; diff --git a/src/matrix/room/RoomSummary.js b/src/matrix/room/RoomSummary.js index 81a68b8f..39b1d1b3 100644 --- a/src/matrix/room/RoomSummary.js +++ b/src/matrix/room/RoomSummary.js @@ -272,7 +272,7 @@ export class RoomSummary { if (data === this._data) { return false; } - const txn = await storage.readWriteTxn([ + const txn = storage.readWriteTxn([ storage.storeNames.roomSummary, ]); try { diff --git a/src/matrix/room/members/load.js b/src/matrix/room/members/load.js index a8648eac..aa14d2fb 100644 --- a/src/matrix/room/members/load.js +++ b/src/matrix/room/members/load.js @@ -18,7 +18,7 @@ limitations under the License. import {RoomMember} from "./RoomMember.js"; async function loadMembers({roomId, storage}) { - const txn = await storage.readTxn([ + const txn = storage.readTxn([ storage.storeNames.roomMembers, ]); const memberDatas = await txn.roomMembers.getAll(roomId); @@ -33,7 +33,7 @@ async function fetchMembers({summary, syncToken, roomId, hsApi, storage, setChan const memberResponse = await hsApi.members(roomId, {at: syncToken}).response(); - const txn = await storage.readWriteTxn([ + const txn = storage.readWriteTxn([ storage.storeNames.roomSummary, storage.storeNames.roomMembers, ]); diff --git a/src/matrix/room/sending/SendQueue.js b/src/matrix/room/sending/SendQueue.js index b256b496..eba5fcf3 100644 --- a/src/matrix/room/sending/SendQueue.js +++ b/src/matrix/room/sending/SendQueue.js @@ -130,7 +130,7 @@ export class SendQueue { } async _tryUpdateEvent(pendingEvent) { - const txn = await this._storage.readWriteTxn([this._storage.storeNames.pendingEvents]); + const txn = this._storage.readWriteTxn([this._storage.storeNames.pendingEvents]); console.log("_tryUpdateEvent: got txn"); try { // pendingEvent might have been removed already here @@ -152,7 +152,7 @@ export class SendQueue { async _createAndStoreEvent(eventType, content) { console.log("_createAndStoreEvent"); - const txn = await this._storage.readWriteTxn([this._storage.storeNames.pendingEvents]); + const txn = this._storage.readWriteTxn([this._storage.storeNames.pendingEvents]); let pendingEvent; try { const pendingEventsStore = txn.pendingEvents; diff --git a/src/matrix/room/timeline/persistence/TimelineReader.js b/src/matrix/room/timeline/persistence/TimelineReader.js index 37b15574..24ad4127 100644 --- a/src/matrix/room/timeline/persistence/TimelineReader.js +++ b/src/matrix/room/timeline/persistence/TimelineReader.js @@ -108,14 +108,14 @@ export class TimelineReader { readFrom(eventKey, direction, amount) { return new ReaderRequest(async r => { - const txn = await this._openTxn(); + const txn = this._openTxn(); return await this._readFrom(eventKey, direction, amount, r, txn); }); } readFromEnd(amount) { return new ReaderRequest(async r => { - const txn = await this._openTxn(); + const txn = this._openTxn(); const liveFragment = await txn.timelineFragments.liveFragment(this._roomId); let entries; // room hasn't been synced yet diff --git a/src/matrix/ssss/index.js b/src/matrix/ssss/index.js index 286744fc..d5bcfe97 100644 --- a/src/matrix/ssss/index.js +++ b/src/matrix/ssss/index.js @@ -19,7 +19,7 @@ import {keyFromPassphrase} from "./passphrase.js"; import {keyFromRecoveryKey} from "./recoveryKey.js"; async function readDefaultKeyDescription(storage) { - const txn = await storage.readTxn([ + const txn = storage.readTxn([ storage.storeNames.accountData ]); const defaultKeyEvent = await txn.accountData.get("m.secret_storage.default_key"); diff --git a/src/matrix/storage/idb/Storage.js b/src/matrix/storage/idb/Storage.js index 9c79b92f..03c2c8ef 100644 --- a/src/matrix/storage/idb/Storage.js +++ b/src/matrix/storage/idb/Storage.js @@ -34,7 +34,7 @@ export class Storage { } } - async readTxn(storeNames) { + readTxn(storeNames) { this._validateStoreNames(storeNames); try { const txn = this._db.transaction(storeNames, "readonly"); @@ -44,7 +44,7 @@ export class Storage { } } - async readWriteTxn(storeNames) { + readWriteTxn(storeNames) { this._validateStoreNames(storeNames); try { const txn = this._db.transaction(storeNames, "readwrite");