Merge pull request #3610 from matrix-org/jryans/alias-cache

Improve room switching performance with alias cache
This commit is contained in:
J. Ryan Stinnett 2019-11-12 18:24:43 +02:00 committed by GitHub
commit c9ca8b9869
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 29 deletions

35
src/RoomAliasCache.js Normal file
View file

@ -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);
}

View file

@ -60,6 +60,7 @@ import AutoDiscoveryUtils from "../../utils/AutoDiscoveryUtils";
import DMRoomMap from '../../utils/DMRoomMap'; import DMRoomMap from '../../utils/DMRoomMap';
import { countRoomsWithNotif } from '../../RoomNotifs'; import { countRoomsWithNotif } from '../../RoomNotifs';
import { setTheme } from "../../theme"; import { setTheme } from "../../theme";
import { storeRoomAliasInCache } from '../../RoomAliasCache';
// Disable warnings for now: we use deprecated bluebird functions // Disable warnings for now: we use deprecated bluebird functions
// and need to migrate, but they spam the console with warnings. // 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); const room = MatrixClientPeg.get().getRoom(roomInfo.room_id);
if (room) { if (room) {
const theAlias = Rooms.getDisplayAliasForRoom(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 // 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. // persist which room is being stored across refreshes and browser quits.

View file

@ -20,6 +20,7 @@ import MatrixClientPeg from '../MatrixClientPeg';
import sdk from '../index'; import sdk from '../index';
import Modal from '../Modal'; import Modal from '../Modal';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import { getCachedRoomIDForAlias, storeRoomAliasInCache } from '../RoomAliasCache';
const INITIAL_STATE = { const INITIAL_STATE = {
// Whether we're joining the currently viewed room (see isJoining()) // 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) { if (payload.room_id) {
const newState = { const newState = {
roomId: payload.room_id, roomId: payload.room_id,
@ -176,34 +177,44 @@ class RoomViewStore extends Store {
this._joinRoom(payload); this._joinRoom(payload);
} }
} else if (payload.room_alias) { } else if (payload.room_alias) {
// Resolve the alias and then do a second dispatch with the room ID acquired // Try the room alias to room ID navigation cache first to avoid
this._setState({ // blocking room navigation on the homeserver.
roomId: null, let roomId = getCachedRoomIDForAlias(payload.room_alias);
initialEventId: null, if (!roomId) {
initialEventPixelOffset: null, // Room alias cache miss, so let's ask the homeserver. Resolve the alias
isInitialEventHighlighted: null, // and then do a second dispatch with the room ID acquired.
roomAlias: payload.room_alias, this._setState({
roomLoading: true, roomId: null,
roomLoadError: null, initialEventId: null,
}); initialEventPixelOffset: null,
MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias).done( isInitialEventHighlighted: null,
(result) => { roomAlias: payload.room_alias,
dis.dispatch({ roomLoading: true,
action: 'view_room', roomLoadError: null,
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,
});
}, (err) => {
dis.dispatch({
action: 'view_room_error',
room_id: null,
room_alias: payload.room_alias,
err: err,
}); });
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;
}
}
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,
}); });
} }
} }