mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-12-23 11:35:04 +01:00
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.
This commit is contained in:
parent
d759e1429f
commit
76381fbca1
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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 => {
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
]);
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
]);
|
||||
|
@ -129,7 +129,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
|
||||
@ -151,7 +151,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;
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user