Add locking to avoid index corruption
When a new room is added there's a fairly good chance that the other events being dispatched will happen in the middle of (for example) the room list being re-sorted. This commit wraps the entire handleRoomUpdate() function for the underlying algorithms in a lock so that if we're unlucky enough to get an update while we're sorting (as the ImportanceAlgorithm splices out what it is sorting) we won't scream about invalid index errors.pull/21833/head
parent
c7a83e65f0
commit
223ee0dbdb
|
@ -179,6 +179,9 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async handleRoomUpdate(room: Room, cause: RoomUpdateCause): Promise<boolean> {
|
public async handleRoomUpdate(room: Room, cause: RoomUpdateCause): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await this.updateLock.acquireAsync();
|
||||||
|
|
||||||
if (cause === RoomUpdateCause.NewRoom || cause === RoomUpdateCause.RoomRemoved) {
|
if (cause === RoomUpdateCause.NewRoom || cause === RoomUpdateCause.RoomRemoved) {
|
||||||
return this.handleSplice(room, cause);
|
return this.handleSplice(room, cause);
|
||||||
}
|
}
|
||||||
|
@ -218,6 +221,9 @@ export class ImportanceAlgorithm extends OrderingAlgorithm {
|
||||||
await this.sortCategory(category);
|
await this.sortCategory(category);
|
||||||
|
|
||||||
return true; // change made
|
return true; // change made
|
||||||
|
} finally {
|
||||||
|
await this.updateLock.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async sortCategory(category: Category) {
|
private async sortCategory(category: Category) {
|
||||||
|
|
|
@ -38,6 +38,9 @@ export class NaturalAlgorithm extends OrderingAlgorithm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async handleRoomUpdate(room, cause): Promise<boolean> {
|
public async handleRoomUpdate(room, cause): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await this.updateLock.acquireAsync();
|
||||||
|
|
||||||
const isSplice = cause === RoomUpdateCause.NewRoom || cause === RoomUpdateCause.RoomRemoved;
|
const isSplice = cause === RoomUpdateCause.NewRoom || cause === RoomUpdateCause.RoomRemoved;
|
||||||
const isInPlace = cause === RoomUpdateCause.Timeline || cause === RoomUpdateCause.ReadReceipt;
|
const isInPlace = cause === RoomUpdateCause.Timeline || cause === RoomUpdateCause.ReadReceipt;
|
||||||
if (!isSplice && !isInPlace) {
|
if (!isSplice && !isInPlace) {
|
||||||
|
@ -56,5 +59,8 @@ export class NaturalAlgorithm extends OrderingAlgorithm {
|
||||||
this.cachedOrderedRooms = await sortRoomsWithAlgorithm(this.cachedOrderedRooms, this.tagId, this.sortingAlgorithm);
|
this.cachedOrderedRooms = await sortRoomsWithAlgorithm(this.cachedOrderedRooms, this.tagId, this.sortingAlgorithm);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
} finally {
|
||||||
|
await this.updateLock.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { RoomUpdateCause, TagID } from "../../models";
|
import { RoomUpdateCause, TagID } from "../../models";
|
||||||
import { SortAlgorithm } from "../models";
|
import { SortAlgorithm } from "../models";
|
||||||
|
import AwaitLock from "await-lock";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a list ordering algorithm. Subclasses should populate the
|
* Represents a list ordering algorithm. Subclasses should populate the
|
||||||
|
@ -25,6 +26,7 @@ import { SortAlgorithm } from "../models";
|
||||||
export abstract class OrderingAlgorithm {
|
export abstract class OrderingAlgorithm {
|
||||||
protected cachedOrderedRooms: Room[];
|
protected cachedOrderedRooms: Room[];
|
||||||
protected sortingAlgorithm: SortAlgorithm;
|
protected sortingAlgorithm: SortAlgorithm;
|
||||||
|
protected readonly updateLock = new AwaitLock();
|
||||||
|
|
||||||
protected constructor(protected tagId: TagID, initialSortingAlgorithm: SortAlgorithm) {
|
protected constructor(protected tagId: TagID, initialSortingAlgorithm: SortAlgorithm) {
|
||||||
// noinspection JSIgnoredPromiseFromCall
|
// noinspection JSIgnoredPromiseFromCall
|
||||||
|
|
Loading…
Reference in New Issue