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 { isNullOrUndefined } from "matrix-js-sdk/src/utils";
import DMRoomMap from "../../../utils/DMRoomMap";
import { EventEmitter } from "events";
import AwaitLock from "await-lock";
import DMRoomMap from "../../../utils/DMRoomMap";
import { arrayDiff, arrayHasDiff } from "../../../utils/arrays";
import { DefaultTagID, RoomUpdateCause, TagID } from "../models";
import {
@ -78,6 +80,7 @@ export class Algorithm extends EventEmitter {
} = {};
private allowedByFilter: Map<IFilterCondition, Room[]> = new Map<IFilterCondition, Room[]>();
private allowedRoomsByFilters: Set<Room> = new Set<Room>();
private stickyLock = new AwaitLock();
/**
* 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.
*/
public async setStickyRoom(val: Room) {
await this.stickyLock.acquireAsync();
try {
await this.updateStickyRoom(val);
} finally {
this.stickyLock.release();
}
}
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 (!this.sortAlgorithms) throw new Error(`Cannot set known rooms without a tag sorting map`);
await this.stickyLock.acquireAsync();
try {
if (!this.updatesInhibited) {
// 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
@ -529,7 +539,7 @@ export class Algorithm extends EventEmitter {
// Before we go any further we need to clear (but remember) the sticky room to
// avoid accidentally duplicating it in the list.
const oldStickyRoom = this._stickyRoom;
await this.updateStickyRoom(null);
if (oldStickyRoom) await this.updateStickyRoom(null);
this.rooms = rooms;
@ -596,6 +606,9 @@ export class Algorithm extends EventEmitter {
}
}
}
} finally {
this.stickyLock.release();
}
}
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");
// 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) {
const isForLastSticky = this._lastStickyRoom && this._lastStickyRoom.room === room;
const isForLastSticky = this._lastStickyRoom?.room === room;
const roomTags = this.roomIdsToTags[room.roomId];
const hasTags = roomTags && roomTags.length > 0;