Fix infinite loop when restoring cached read receipts (#2963)
This commit is contained in:
+5
-11
@@ -2079,8 +2079,13 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
||||
room: this,
|
||||
client: this.client,
|
||||
pendingEventOrdering: this.opts.pendingEventOrdering,
|
||||
receipts: this.cachedThreadReadReceipts.get(threadId) ?? [],
|
||||
});
|
||||
|
||||
// All read receipts should now come down from sync, we do not need to keep
|
||||
// a reference to the cached receipts anymore.
|
||||
this.cachedThreadReadReceipts.delete(threadId);
|
||||
|
||||
// This is necessary to be able to jump to events in threads:
|
||||
// If we jump to an event in a thread where neither the event, nor the root,
|
||||
// nor any thread event are loaded yet, we'll load the event as well as the thread root, create the thread,
|
||||
@@ -2110,17 +2115,6 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
|
||||
if (this.threadsReady) {
|
||||
this.updateThreadRootEvents(thread, toStartOfTimeline, false);
|
||||
}
|
||||
|
||||
// Pulling all the cached thread read receipts we've discovered when we
|
||||
// did an initial sync, and applying them to the thread now that it exists
|
||||
// on the client side
|
||||
if (this.cachedThreadReadReceipts.has(threadId)) {
|
||||
for (const { event, synthetic } of this.cachedThreadReadReceipts.get(threadId)!) {
|
||||
this.addReceipt(event, synthetic);
|
||||
}
|
||||
this.cachedThreadReadReceipts.delete(threadId);
|
||||
}
|
||||
|
||||
this.emit(ThreadEvent.New, thread, toStartOfTimeline);
|
||||
|
||||
return thread;
|
||||
|
||||
+24
-1
@@ -27,7 +27,7 @@ import { RoomState } from "./room-state";
|
||||
import { ServerControlledNamespacedValue } from "../NamespacedValue";
|
||||
import { logger } from "../logger";
|
||||
import { ReadReceipt } from "./read-receipt";
|
||||
import { ReceiptType } from "../@types/read_receipts";
|
||||
import { Receipt, ReceiptContent, ReceiptType } from "../@types/read_receipts";
|
||||
|
||||
export enum ThreadEvent {
|
||||
New = "Thread.new",
|
||||
@@ -50,6 +50,7 @@ interface IThreadOpts {
|
||||
room: Room;
|
||||
client: MatrixClient;
|
||||
pendingEventOrdering?: PendingEventOrdering;
|
||||
receipts?: { event: MatrixEvent; synthetic: boolean }[];
|
||||
}
|
||||
|
||||
export enum FeatureSupport {
|
||||
@@ -127,6 +128,8 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
||||
this.room.on(RoomEvent.LocalEchoUpdated, this.onEcho);
|
||||
this.timelineSet.on(RoomEvent.Timeline, this.onTimelineEvent);
|
||||
|
||||
this.processReceipts(opts.receipts);
|
||||
|
||||
// even if this thread is thought to be originating from this client, we initialise it as we may be in a
|
||||
// gappy sync and a thread around this event may already exist.
|
||||
this.updateThreadMetadata();
|
||||
@@ -284,6 +287,26 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
|
||||
this.timeline = this.events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the receipts that were caught during initial sync
|
||||
* When clients become aware of a thread, they try to retrieve those read receipts
|
||||
* and apply them to the current thread
|
||||
* @param receipts - A collection of the receipts cached from initial sync
|
||||
*/
|
||||
private processReceipts(receipts: { event: MatrixEvent; synthetic: boolean }[] = []): void {
|
||||
for (const { event, synthetic } of receipts) {
|
||||
const content = event.getContent<ReceiptContent>();
|
||||
Object.keys(content).forEach((eventId: string) => {
|
||||
Object.keys(content[eventId]).forEach((receiptType: ReceiptType | string) => {
|
||||
Object.keys(content[eventId][receiptType]).forEach((userId: string) => {
|
||||
const receipt = content[eventId][receiptType][userId] as Receipt;
|
||||
this.addReceiptToStructure(eventId, receiptType as ReceiptType, userId, receipt, synthetic);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private getRootEventBundledRelationship(rootEvent = this.rootEvent): IThreadBundledRelationship | undefined {
|
||||
return rootEvent?.getServerAggregatedRelation<IThreadBundledRelationship>(THREAD_RELATION_TYPE.name);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user