From 7f0d36cf79f7e294a988070ccda7d0fb79da1b0a Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 25 Sep 2020 10:44:19 +0200 Subject: [PATCH 1/5] remove double negation --- src/matrix/Sync.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/Sync.js b/src/matrix/Sync.js index 02d4f8b2..678578e1 100644 --- a/src/matrix/Sync.js +++ b/src/matrix/Sync.js @@ -120,7 +120,7 @@ export class Sync { } } catch (err) { this._status.set(SyncStatus.Stopped); - if (!(err instanceof AbortError)) { + if (err.name !== AbortError) { console.warn("stopping sync because of error"); console.error(err); this._error = err; From bcca23bac93f6337926f1132ac7c639adf1c4fea Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 25 Sep 2020 10:44:29 +0200 Subject: [PATCH 2/5] retry sync on timeout, even for incremental sync --- src/matrix/Sync.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/matrix/Sync.js b/src/matrix/Sync.js index 678578e1..cee8347d 100644 --- a/src/matrix/Sync.js +++ b/src/matrix/Sync.js @@ -119,6 +119,11 @@ export class Sync { this._status.set(SyncStatus.Syncing); } } catch (err) { + // retry same request on timeout + if (err.name === "ConnectionError" && err.isTimeout) { + // don't run afterSyncCompleted + continue; + } this._status.set(SyncStatus.Stopped); if (err.name !== AbortError) { console.warn("stopping sync because of error"); From 134b04c78264cb3407d45fd4449e4fac0eba8058 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 25 Sep 2020 10:45:00 +0200 Subject: [PATCH 3/5] make flushing room key shares reentrant as it can be called from Room.start while still running. --- src/matrix/e2ee/RoomEncryption.js | 42 +++++++++++++++++++------------ 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/matrix/e2ee/RoomEncryption.js b/src/matrix/e2ee/RoomEncryption.js index 2c23933d..94af64d1 100644 --- a/src/matrix/e2ee/RoomEncryption.js +++ b/src/matrix/e2ee/RoomEncryption.js @@ -54,6 +54,7 @@ export class RoomEncryption { this._notifyMissingMegolmSession = notifyMissingMegolmSession; this._clock = clock; this._disposed = false; + this._isFlushingRoomKeyShares = false; } async enableSessionBackup(sessionBackup) { @@ -321,25 +322,34 @@ export class RoomEncryption { } async flushPendingRoomKeyShares(hsApi, operations = null) { - if (!operations) { - const txn = await this._storage.readTxn([this._storage.storeNames.operations]); - operations = await txn.operations.getAllByTypeAndScope("share_room_key", this._room.id); + // this has to be reentrant as it can be called from Room.start while still running + if (this._isFlushingRoomKeyShares) { + return; } - for (const operation of operations) { - // just to be sure - if (operation.type !== "share_room_key") { - continue; + this._isFlushingRoomKeyShares = true; + try { + if (!operations) { + const txn = await this._storage.readTxn([this._storage.storeNames.operations]); + operations = await txn.operations.getAllByTypeAndScope("share_room_key", this._room.id); } - 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]); - try { - removeTxn.operations.remove(operation.id); - } catch (err) { - removeTxn.abort(); - throw err; + for (const operation of operations) { + // just to be sure + if (operation.type !== "share_room_key") { + continue; + } + 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]); + try { + removeTxn.operations.remove(operation.id); + } catch (err) { + removeTxn.abort(); + throw err; + } + await removeTxn.complete(); } - await removeTxn.complete(); + } finally { + this._isFlushingRoomKeyShares = false; } } From e175e9ac8baa11287a308eeff57f24a22af96f9d Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 25 Sep 2020 10:45:34 +0200 Subject: [PATCH 4/5] cleanup --- src/matrix/net/HomeServerApi.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matrix/net/HomeServerApi.js b/src/matrix/net/HomeServerApi.js index 63d5c830..83007953 100644 --- a/src/matrix/net/HomeServerApi.js +++ b/src/matrix/net/HomeServerApi.js @@ -75,7 +75,7 @@ export class HomeServerApi { method, headers, body: bodyString, - timeout: options && options.timeout + timeout: options?.timeout }); const wrapper = new RequestWrapper(method, url, requestResult); From 27a8ef46045244a9949e921c9b448ee6e174add6 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 25 Sep 2020 10:45:41 +0200 Subject: [PATCH 5/5] add comment how timeouts interact with the reconnector --- src/matrix/net/HomeServerApi.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/matrix/net/HomeServerApi.js b/src/matrix/net/HomeServerApi.js index 83007953..3c5eda8a 100644 --- a/src/matrix/net/HomeServerApi.js +++ b/src/matrix/net/HomeServerApi.js @@ -82,6 +82,10 @@ export class HomeServerApi { if (this._reconnector) { wrapper.response().catch(err => { + // Some endpoints such as /sync legitimately time-out + // (which is also reported as a ConnectionError) and will re-attempt, + // but spinning up the reconnector in this case is ok, + // as all code ran on session and sync start should be reentrant if (err.name === "ConnectionError") { this._reconnector.onRequestFailed(this); }