Fix issue with room duplication caused by filtering and selecting room using keyboard

Wrap sticky room updates in lock to prevent setStickyRoom running in middle of setKnownRooms
pull/21833/head
Michael Telatynski 2021-07-16 08:49:19 +01:00
parent 376533e709
commit 32cc48ff7a
1 changed files with 80 additions and 67 deletions

View File

@ -16,8 +16,10 @@ limitations under the License.
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; import { isNullOrUndefined } from "matrix-js-sdk/src/utils";
import DMRoomMap from "../../../utils/DMRoomMap";
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import AwaitLock from "await-lock";
import DMRoomMap from "../../../utils/DMRoomMap";
import { arrayDiff, arrayHasDiff } from "../../../utils/arrays"; import { arrayDiff, arrayHasDiff } from "../../../utils/arrays";
import { DefaultTagID, RoomUpdateCause, TagID } from "../models"; import { DefaultTagID, RoomUpdateCause, TagID } from "../models";
import { import {
@ -78,6 +80,7 @@ export class Algorithm extends EventEmitter {
} = {}; } = {};
private allowedByFilter: Map<IFilterCondition, Room[]> = new Map<IFilterCondition, Room[]>(); private allowedByFilter: Map<IFilterCondition, Room[]> = new Map<IFilterCondition, Room[]>();
private allowedRoomsByFilters: Set<Room> = new Set<Room>(); private allowedRoomsByFilters: Set<Room> = new Set<Room>();
private stickyLock = new AwaitLock();
/** /**
* Set to true to suspend emissions of algorithm updates. * Set to true to suspend emissions of algorithm updates.
@ -123,7 +126,12 @@ export class Algorithm extends EventEmitter {
* @param val The new room to sticky. * @param val The new room to sticky.
*/ */
public async setStickyRoom(val: Room) { public async setStickyRoom(val: Room) {
await this.stickyLock.acquireAsync();
try {
await this.updateStickyRoom(val); await this.updateStickyRoom(val);
} finally {
this.stickyLock.release();
}
} }
public getTagSorting(tagId: TagID): SortAlgorithm { public getTagSorting(tagId: TagID): SortAlgorithm {
@ -519,6 +527,8 @@ export class Algorithm extends EventEmitter {
if (isNullOrUndefined(rooms)) throw new Error(`Array of rooms cannot be null`); if (isNullOrUndefined(rooms)) throw new Error(`Array of rooms cannot be null`);
if (!this.sortAlgorithms) throw new Error(`Cannot set known rooms without a tag sorting map`); if (!this.sortAlgorithms) throw new Error(`Cannot set known rooms without a tag sorting map`);
await this.stickyLock.acquireAsync();
try {
if (!this.updatesInhibited) { if (!this.updatesInhibited) {
// We only log this if we're expecting to be publishing updates, which means that // We only log this if we're expecting to be publishing updates, which means that
// this could be an unexpected invocation. If we're inhibited, then this is probably // this could be an unexpected invocation. If we're inhibited, then this is probably
@ -529,7 +539,7 @@ export class Algorithm extends EventEmitter {
// Before we go any further we need to clear (but remember) the sticky room to // Before we go any further we need to clear (but remember) the sticky room to
// avoid accidentally duplicating it in the list. // avoid accidentally duplicating it in the list.
const oldStickyRoom = this._stickyRoom; const oldStickyRoom = this._stickyRoom;
await this.updateStickyRoom(null); if (oldStickyRoom) await this.updateStickyRoom(null);
this.rooms = rooms; this.rooms = rooms;
@ -596,6 +606,9 @@ export class Algorithm extends EventEmitter {
} }
} }
} }
} finally {
this.stickyLock.release();
}
} }
public getTagsForRoom(room: Room): TagID[] { public getTagsForRoom(room: Room): TagID[] {
@ -685,9 +698,9 @@ export class Algorithm extends EventEmitter {
if (!this.algorithms) throw new Error("Not ready: no algorithms to determine tags from"); if (!this.algorithms) throw new Error("Not ready: no algorithms to determine tags from");
// Note: check the isSticky against the room ID just in case the reference is wrong // Note: check the isSticky against the room ID just in case the reference is wrong
const isSticky = this._stickyRoom && this._stickyRoom.room && this._stickyRoom.room.roomId === room.roomId; const isSticky = this._stickyRoom?.room?.roomId === room.roomId;
if (cause === RoomUpdateCause.NewRoom) { if (cause === RoomUpdateCause.NewRoom) {
const isForLastSticky = this._lastStickyRoom && this._lastStickyRoom.room === room; const isForLastSticky = this._lastStickyRoom?.room === room;
const roomTags = this.roomIdsToTags[room.roomId]; const roomTags = this.roomIdsToTags[room.roomId];
const hasTags = roomTags && roomTags.length > 0; const hasTags = roomTags && roomTags.length > 0;