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.
This commit is contained in:
parent
c7a83e65f0
commit
223ee0dbdb
3 changed files with 69 additions and 55 deletions
|
@ -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…
Add table
Add a link
Reference in a new issue