From d72dedb0cee9868792256bc8e34ee1e76e38c8dc Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Tue, 12 Nov 2019 11:43:18 +0000 Subject: [PATCH 1/2] Cache room alias to room ID mapping in memory This adds very basic cache (literally just a `Map` for now) to store room alias to room ID mappings. The improves the perceived performance of Riot when switching rooms via browser navigation (back / forward), as we no longer try to resolve the room alias every time. The cache is only in memory, so reloading manually or as part of the clear cache process will start afresh. Fixes https://github.com/vector-im/riot-web/issues/10020 --- src/RoomAliasCache.js | 35 +++++++++++++++++++++++++ src/components/structures/MatrixChat.js | 8 +++++- src/stores/RoomViewStore.js | 30 ++++++++++++++++----- 3 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 src/RoomAliasCache.js diff --git a/src/RoomAliasCache.js b/src/RoomAliasCache.js new file mode 100644 index 0000000000..bb511ba4d7 --- /dev/null +++ b/src/RoomAliasCache.js @@ -0,0 +1,35 @@ +/* +Copyright 2019 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +/** + * This is meant to be a cache of room alias to room ID so that moving between + * rooms happens smoothly (for example using browser back / forward buttons). + * + * For the moment, it's in memory only and so only applies for the current + * session for simplicity, but could be extended further in the future. + * + * A similar thing could also be achieved via `pushState` with a state object, + * but keeping it separate like this seems easier in case we do want to extend. + */ +const aliasToIDMap = new Map(); + +export function storeRoomAliasInCache(alias, id) { + aliasToIDMap.set(alias, id); +} + +export function getCachedRoomIDForAlias(alias) { + return aliasToIDMap.get(alias); +} diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index da67416400..6cc86bf6d7 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -60,6 +60,7 @@ import AutoDiscoveryUtils from "../../utils/AutoDiscoveryUtils"; import DMRoomMap from '../../utils/DMRoomMap'; import { countRoomsWithNotif } from '../../RoomNotifs'; import { setTheme } from "../../theme"; +import { storeRoomAliasInCache } from '../../RoomAliasCache'; // Disable warnings for now: we use deprecated bluebird functions // and need to migrate, but they spam the console with warnings. @@ -866,7 +867,12 @@ export default createReactClass({ const room = MatrixClientPeg.get().getRoom(roomInfo.room_id); if (room) { const theAlias = Rooms.getDisplayAliasForRoom(room); - if (theAlias) presentedId = theAlias; + if (theAlias) { + presentedId = theAlias; + // Store display alias of the presented room in cache to speed future + // navigation. + storeRoomAliasInCache(theAlias, room.roomId); + } // Store this as the ID of the last room accessed. This is so that we can // persist which room is being stored across refreshes and browser quits. diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index 7e1b06c0bf..e860ed8b24 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -20,6 +20,7 @@ import MatrixClientPeg from '../MatrixClientPeg'; import sdk from '../index'; import Modal from '../Modal'; import { _t } from '../languageHandler'; +import { getCachedRoomIDForAlias, storeRoomAliasInCache } from '../RoomAliasCache'; const INITIAL_STATE = { // Whether we're joining the currently viewed room (see isJoining()) @@ -137,7 +138,7 @@ class RoomViewStore extends Store { } } - _viewRoom(payload) { + async _viewRoom(payload) { if (payload.room_id) { const newState = { roomId: payload.room_id, @@ -176,6 +177,22 @@ class RoomViewStore extends Store { this._joinRoom(payload); } } else if (payload.room_alias) { + // Try the room alias to room ID navigation cache first to avoid + // blocking room navigation on the homeserver. + const roomId = getCachedRoomIDForAlias(payload.room_alias); + if (roomId) { + dis.dispatch({ + action: 'view_room', + room_id: roomId, + event_id: payload.event_id, + highlighted: payload.highlighted, + room_alias: payload.room_alias, + auto_join: payload.auto_join, + oob_data: payload.oob_data, + }); + return; + } + // Room alias cache miss, so let's ask the homeserver. // Resolve the alias and then do a second dispatch with the room ID acquired this._setState({ roomId: null, @@ -186,8 +203,9 @@ class RoomViewStore extends Store { roomLoading: true, roomLoadError: null, }); - MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias).done( - (result) => { + try { + const result = await MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias); + storeRoomAliasInCache(payload.room_alias, result.room_id); dis.dispatch({ action: 'view_room', room_id: result.room_id, @@ -197,14 +215,14 @@ class RoomViewStore extends Store { auto_join: payload.auto_join, oob_data: payload.oob_data, }); - }, (err) => { + } catch (err) { dis.dispatch({ action: 'view_room_error', room_id: null, room_alias: payload.room_alias, - err: err, + err, }); - }); + } } } From 3f2b77189e31c0cb3617d78105987190f10502a9 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Tue, 12 Nov 2019 13:29:01 +0000 Subject: [PATCH 2/2] Simplify dispatch blocks --- src/stores/RoomViewStore.js | 75 +++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 41 deletions(-) diff --git a/src/stores/RoomViewStore.js b/src/stores/RoomViewStore.js index e860ed8b24..6a405124f4 100644 --- a/src/stores/RoomViewStore.js +++ b/src/stores/RoomViewStore.js @@ -179,50 +179,43 @@ class RoomViewStore extends Store { } else if (payload.room_alias) { // Try the room alias to room ID navigation cache first to avoid // blocking room navigation on the homeserver. - const roomId = getCachedRoomIDForAlias(payload.room_alias); - if (roomId) { - dis.dispatch({ - action: 'view_room', - room_id: roomId, - event_id: payload.event_id, - highlighted: payload.highlighted, - room_alias: payload.room_alias, - auto_join: payload.auto_join, - oob_data: payload.oob_data, + let roomId = getCachedRoomIDForAlias(payload.room_alias); + if (!roomId) { + // Room alias cache miss, so let's ask the homeserver. Resolve the alias + // and then do a second dispatch with the room ID acquired. + this._setState({ + roomId: null, + initialEventId: null, + initialEventPixelOffset: null, + isInitialEventHighlighted: null, + roomAlias: payload.room_alias, + roomLoading: true, + roomLoadError: null, }); - return; + try { + const result = await MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias); + storeRoomAliasInCache(payload.room_alias, result.room_id); + roomId = result.room_id; + } catch (err) { + dis.dispatch({ + action: 'view_room_error', + room_id: null, + room_alias: payload.room_alias, + err, + }); + return; + } } - // Room alias cache miss, so let's ask the homeserver. - // Resolve the alias and then do a second dispatch with the room ID acquired - this._setState({ - roomId: null, - initialEventId: null, - initialEventPixelOffset: null, - isInitialEventHighlighted: null, - roomAlias: payload.room_alias, - roomLoading: true, - roomLoadError: null, + + dis.dispatch({ + action: 'view_room', + room_id: roomId, + event_id: payload.event_id, + highlighted: payload.highlighted, + room_alias: payload.room_alias, + auto_join: payload.auto_join, + oob_data: payload.oob_data, }); - try { - const result = await MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias); - storeRoomAliasInCache(payload.room_alias, result.room_id); - dis.dispatch({ - action: 'view_room', - room_id: result.room_id, - event_id: payload.event_id, - highlighted: payload.highlighted, - room_alias: payload.room_alias, - auto_join: payload.auto_join, - oob_data: payload.oob_data, - }); - } catch (err) { - dis.dispatch({ - action: 'view_room_error', - room_id: null, - room_alias: payload.room_alias, - err, - }); - } } }