Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid unnecessary work when processing threads #3530

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion spec/unit/room.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2559,7 +2559,7 @@
let prom = emitPromise(room, ThreadEvent.New);
await room.addLiveEvents([randomMessage, threadRoot, threadResponse]);
const thread: Thread = await prom;
await emitPromise(room, ThreadEvent.Update);
await Promise.all([emitPromise(room, RoomEvent.TimelineReset), emitPromise(room, ThreadEvent.Update)]);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This waits for the correct signal that Thread.constructor has completed


expect(thread.initialEventsFetched).toBeTruthy();
expect(thread.replyToEvent!.event).toEqual(threadResponse.event);
Expand All @@ -2586,7 +2586,7 @@
prom = emitPromise(room, ThreadEvent.Update);
await room.addLiveEvents([threadResponseEdit]);
await prom;
expect(thread.replyToEvent!.getContent().body).toBe(threadResponseEdit.getContent()["m.new_content"].body);

Check failure on line 2589 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node 18)

Room › threads › Edits update the lastReply event

expect(received).toBe(expected) // Object.is equality Expected: "Edit of :: $148-0.10162493779865489-0.5726972111245756 :: 0.1780233692601132" Received: "* Edit of :: $148-0.10162493779865489-0.5726972111245756 :: 0.1780233692601132" at Object.toBe (spec/unit/room.spec.ts:2589:60)

Check failure on line 2589 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node latest)

Room › threads › Edits update the lastReply event

expect(received).toBe(expected) // Object.is equality Expected: "Edit of :: $148-0.16206413805628284-0.43054447892088143 :: 0.7629307935805802" Received: "* Edit of :: $148-0.16206413805628284-0.43054447892088143 :: 0.7629307935805802" at Object.toBe (spec/unit/room.spec.ts:2589:60)
});

it("Redactions to thread responses decrement the length", async () => {
Expand Down Expand Up @@ -2619,7 +2619,7 @@
const thread = await prom;
await emitPromise(room, ThreadEvent.Update);

expect(thread).toHaveLength(2);

Check failure on line 2622 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node 18)

Room › threads › Redactions to thread responses decrement the length

expect(received).toHaveLength(expected) Expected length: 2 Received length: 0 Received object: {"_currentUserParticipated": false, "_events": {"Room.timeline": [Function forSource], "Room.timelineReset": [Function forSource], "Thread.delete": [Function forSource], "Thread.newReply": [Function forSource], "Thread.update": [Array]}, "_eventsCount": 5, "_maxListeners": undefined, "client": {"_events": [Object], "_eventsCount": 3, "_maxListeners": undefined, "_secretStorage": [ServerSideSecretStorageImpl], "baseUrl": "http://alice.example.com.test.server", "cachedCapabilities": undefined, "callEventHandler": undefined, "canResetTimelineCallback": undefined, "canSupport": [Map], "canSupportVoip": false, "checkTurnServersIntervalID": undefined, "clientOpts": undefined, "clientRunning": false, "clientWellKnown": undefined, "clientWellKnownIntervalID": undefined, "clientWellKnownPromise": undefined, "credentials": [Object], "crypto": undefined, "cryptoBackend": undefined, "cryptoCallbacks": [Object], "cryptoStore": [LocalStorageCryptoStore], "deviceId": "alicedevice", "exportedOlmDeviceToImport": undefined, "fallbackICEServerAllowed": false, "fetchRoomEvent": [Function anonymous], "fixupRoomNotifications": [Function anonymous], "forceTURN": false, "getRoom": [Function anonymous], "groupCallEventHandler": undefined, "http": [MatrixHttpApi], "iceCandidatePoolSize": 0, "idBaseUrl": undefined, "identityServer": undefined, "ignoredInvites": [IgnoredInvites], "isGuestAccount": false, "isVoipWithNoMediaAllowed": false, "mediaHandler": [MediaHandler], "notifTimelineSet": null, "olmVersion": null, "ongoingScrollbacks": [Object], "peekSync": null, "pendingEventEncryption": [Map], "pickleKey": undefined, "pushProcessor": [PushProcessor], "pushRules": undefined, "reEmitter": [TypedReEmitter], "roomList": [RoomList], "roomNameGenerator": undefined, "scheduler": [MatrixScheduler], "serverVersionsPromise": undefined, "sessionId": "xJsgpuFWpa", "startCallEventHandler": [Function anonymous], "store": [MemoryStore], "supportsCallTransfer": false, "supportsThreads": [Function anonymous], "syncApi": undefined, "syncLeftRoomsPromise": undefined, "syncedLeftRooms": false, "timelineSupport": false, "toDeviceMessageQueue": [ToDeviceMessageQueue], "turnServers": [Array], "turnServersExpiry": 0, "txnCtr": 0, "urlPreviewCache": [Object], "useE2eForGroupCall": true, "usingExternalCrypto": false, "verificationMethods": undefined, Symbol(kCapture): false}, "fetchRootEvent": [Function anonymous], "id": "$150-0.28062679192085516-0.4547709513595304", "initialEventsFetched": true, "lastEvent": [Object], "lastPendingEvent": undefined, "onBeforeRedaction": [Function anonymous], "onEcho": [Function anonymous], "onLocalEcho": [Function anonymous], "onRedaction": [Function anonymous], "onTimelineEvent": [Function anonymous], "pendingEventOrdering": "chronological", "pendingReplyCount": 0, "processRootEvent": [Function anonymous], "reEmitter": {"reEmitters": WeakMap {}, "target": [Circular]}, "receiptCacheByEventId": Map {"$152-0.10641010696150066-0.4839883892405439" => [Array]}, "receipts": Map {"m.read" => [Map]}, "replayEvents": null, "replyCount": 0, "room": {"_events": [Object], "_eventsCount": 3, "_maxListeners": 100, "accountData": [Map], "applyRedaction": [Function anonymous], "blacklistUnverifiedDevices": undefined, "cachedThreadReadReceipts": [Map], "client": [MatrixClient], "currentState": [RoomState], "filteredTimelineSets": [Object], "getTypeWarning": false, "getVersionWarning": false, "lastThread": [Circular], "membersPromise": [Promise], "myUserId": "@alice:bar", "name": "!foo:bar", "normalizedName": "!foo:bar", "notificationCounts": [Object], "oldState": [RoomState], "oldestThreadedReceiptTs": Infinity, "opts": [Object], "pendingEventList": undefined, "polls": [Map], "reEmitter": [TypedReEmitter], "receiptCacheByEventId": [Map], "receipts": [Map], "relations": [RelationsContainer], "roomId": "!foo:bar", "selfMembership": undefined, "summary": null, "summaryHeroes": null, "tags": [Object], "threadNotifications": [Map], "threadTimelineSetsPromise": null

Check failure on line 2622 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node latest)

Room › threads › Redactions to thread responses decrement the length

expect(received).toHaveLength(expected) Expected length: 2 Received length: 0 Received object: {"_currentUserParticipated": false, "_events": {"Room.timeline": [Function forSource], "Room.timelineReset": [Function forSource], "Thread.delete": [Function forSource], "Thread.newReply": [Function forSource], "Thread.update": [Array]}, "_eventsCount": 5, "_maxListeners": undefined, "client": {"_events": [Object], "_eventsCount": 3, "_maxListeners": undefined, "_secretStorage": [ServerSideSecretStorageImpl], "baseUrl": "http://alice.example.com.test.server", "cachedCapabilities": undefined, "callEventHandler": undefined, "canResetTimelineCallback": undefined, "canSupport": [Map], "canSupportVoip": false, "checkTurnServersIntervalID": undefined, "clientOpts": undefined, "clientRunning": false, "clientWellKnown": undefined, "clientWellKnownIntervalID": undefined, "clientWellKnownPromise": undefined, "credentials": [Object], "crypto": undefined, "cryptoBackend": undefined, "cryptoCallbacks": [Object], "cryptoStore": [LocalStorageCryptoStore], "deviceId": "alicedevice", "exportedOlmDeviceToImport": undefined, "fallbackICEServerAllowed": false, "fetchRoomEvent": [Function anonymous], "fixupRoomNotifications": [Function anonymous], "forceTURN": false, "getRoom": [Function anonymous], "groupCallEventHandler": undefined, "http": [MatrixHttpApi], "iceCandidatePoolSize": 0, "idBaseUrl": undefined, "identityServer": undefined, "ignoredInvites": [IgnoredInvites], "isGuestAccount": false, "isVoipWithNoMediaAllowed": false, "mediaHandler": [MediaHandler], "notifTimelineSet": null, "olmVersion": null, "ongoingScrollbacks": [Object], "peekSync": null, "pendingEventEncryption": [Map], "pickleKey": undefined, "pushProcessor": [PushProcessor], "pushRules": undefined, "reEmitter": [TypedReEmitter], "roomList": [RoomList], "roomNameGenerator": undefined, "scheduler": [MatrixScheduler], "serverVersionsPromise": undefined, "sessionId": "smaGdEDU9X", "startCallEventHandler": [Function anonymous], "store": [MemoryStore], "supportsCallTransfer": false, "supportsThreads": [Function anonymous], "syncApi": undefined, "syncLeftRoomsPromise": undefined, "syncedLeftRooms": false, "timelineSupport": false, "toDeviceMessageQueue": [ToDeviceMessageQueue], "turnServers": [Array], "turnServersExpiry": 0, "txnCtr": 0, "urlPreviewCache": [Object], "useE2eForGroupCall": true, "usingExternalCrypto": false, "verificationMethods": undefined, Symbol(kCapture): false}, "fetchRootEvent": [Function anonymous], "id": "$150-0.285049034466216-0.7476483881568063", "initialEventsFetched": true, "lastEvent": [Object], "lastPendingEvent": undefined, "onBeforeRedaction": [Function anonymous], "onEcho": [Function anonymous], "onLocalEcho": [Function anonymous], "onRedaction": [Function anonymous], "onTimelineEvent": [Function anonymous], "pendingEventOrdering": "chronological", "pendingReplyCount": 0, "processRootEvent": [Function anonymous], "reEmitter": {"reEmitters": WeakMap {}, "target": [Circular]}, "receiptCacheByEventId": Map {"$152-0.9134398723591319-0.9783094558060816" => [Array]}, "receipts": Map {"m.read" => [Map]}, "replayEvents": null, "replyCount": 0, "room": {"_events": [Object], "_eventsCount": 3, "_maxListeners": 100, "accountData": [Map], "applyRedaction": [Function anonymous], "blacklistUnverifiedDevices": undefined, "cachedThreadReadReceipts": [Map], "client": [MatrixClient], "currentState": [RoomState], "filteredTimelineSets": [Object], "getTypeWarning": false, "getVersionWarning": false, "lastThread": [Circular], "membersPromise": [Promise], "myUserId": "@alice:bar", "name": "!foo:bar", "normalizedName": "!foo:bar", "notificationCounts": [Object], "oldState": [RoomState], "oldestThreadedReceiptTs": Infinity, "opts": [Object], "pendingEventList": undefined, "polls": [Map], "reEmitter": [TypedReEmitter], "receiptCacheByEventId": [Map], "receipts": [Map], "relations": [RelationsContainer], "roomId": "!foo:bar", "selfMembership": undefined, "summary": null, "summaryHeroes": null, "tags": [Object], "threadNotifications": [Map], "threadTimelineSetsPromise": null, "
expect(thread.replyToEvent.getId()).toBe(threadResponse2.getId());

thread.timelineSet.addEventToTimeline(threadResponse1, thread.liveTimeline, {
Expand Down Expand Up @@ -2687,7 +2687,7 @@
const thread = await prom;
await emitPromise(room, ThreadEvent.Update);

expect(thread).toHaveLength(2);

Check failure on line 2690 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node 18)

Room › threads › Redactions to reactions in threads do not decrement the length

expect(received).toHaveLength(expected) Expected length: 2 Received length: 0 Received object: {"_currentUserParticipated": false, "_events": {"Room.timeline": [Function forSource], "Room.timelineReset": [Function forSource], "Thread.delete": [Function forSource], "Thread.newReply": [Function forSource], "Thread.update": [Array]}, "_eventsCount": 5, "_maxListeners": undefined, "client": {"_events": [Object], "_eventsCount": 3, "_maxListeners": undefined, "_secretStorage": [ServerSideSecretStorageImpl], "baseUrl": "http://alice.example.com.test.server", "cachedCapabilities": undefined, "callEventHandler": undefined, "canResetTimelineCallback": undefined, "canSupport": [Map], "canSupportVoip": false, "checkTurnServersIntervalID": undefined, "clientOpts": undefined, "clientRunning": false, "clientWellKnown": undefined, "clientWellKnownIntervalID": undefined, "clientWellKnownPromise": undefined, "credentials": [Object], "crypto": undefined, "cryptoBackend": undefined, "cryptoCallbacks": [Object], "cryptoStore": [LocalStorageCryptoStore], "deviceId": "alicedevice", "exportedOlmDeviceToImport": undefined, "fallbackICEServerAllowed": false, "fetchRoomEvent": [Function anonymous], "fixupRoomNotifications": [Function anonymous], "forceTURN": false, "getRoom": [Function anonymous], "groupCallEventHandler": undefined, "http": [MatrixHttpApi], "iceCandidatePoolSize": 0, "idBaseUrl": undefined, "identityServer": undefined, "ignoredInvites": [IgnoredInvites], "isGuestAccount": false, "isVoipWithNoMediaAllowed": false, "mediaHandler": [MediaHandler], "notifTimelineSet": null, "olmVersion": null, "ongoingScrollbacks": [Object], "peekSync": null, "pendingEventEncryption": [Map], "pickleKey": undefined, "pushProcessor": [PushProcessor], "pushRules": undefined, "reEmitter": [TypedReEmitter], "roomList": [RoomList], "roomNameGenerator": undefined, "scheduler": [MatrixScheduler], "serverVersionsPromise": undefined, "sessionId": "mqyHeR7lVv", "startCallEventHandler": [Function anonymous], "store": [MemoryStore], "supportsCallTransfer": false, "supportsThreads": [Function anonymous], "syncApi": undefined, "syncLeftRoomsPromise": undefined, "syncedLeftRooms": false, "timelineSupport": false, "toDeviceMessageQueue": [ToDeviceMessageQueue], "turnServers": [Array], "turnServersExpiry": 0, "txnCtr": 0, "urlPreviewCache": [Object], "useE2eForGroupCall": true, "usingExternalCrypto": false, "verificationMethods": undefined, Symbol(kCapture): false}, "fetchRootEvent": [Function anonymous], "id": "$153-0.8802908195037975-0.44579245729282646", "initialEventsFetched": true, "lastEvent": [Object], "lastPendingEvent": undefined, "onBeforeRedaction": [Function anonymous], "onEcho": [Function anonymous], "onLocalEcho": [Function anonymous], "onRedaction": [Function anonymous], "onTimelineEvent": [Function anonymous], "pendingEventOrdering": "chronological", "pendingReplyCount": 0, "processRootEvent": [Function anonymous], "reEmitter": {"reEmitters": WeakMap {}, "target": [Circular]}, "receiptCacheByEventId": Map {"$156-0.8533920610814836-0.12831528590551788" => [Array]}, "receipts": Map {"m.read" => [Map]}, "replayEvents": null, "replyCount": 0, "room": {"_events": [Object], "_eventsCount": 3, "_maxListeners": 100, "accountData": [Map], "applyRedaction": [Function anonymous], "blacklistUnverifiedDevices": undefined, "cachedThreadReadReceipts": [Map], "client": [MatrixClient], "currentState": [RoomState], "filteredTimelineSets": [Object], "getTypeWarning": false, "getVersionWarning": false, "lastThread": [Circular], "membersPromise": [Promise], "myUserId": "@alice:bar", "name": "!foo:bar", "normalizedName": "!foo:bar", "notificationCounts": [Object], "oldState": [RoomState], "oldestThreadedReceiptTs": Infinity, "opts": [Object], "pendingEventList": undefined, "polls": [Map], "reEmitter": [TypedReEmitter], "receiptCacheByEventId": [Map], "receipts": [Map], "relations": [RelationsContainer], "roomId": "!foo:bar", "selfMembership": undefined, "summary": null, "summaryHeroes": null, "tags": [Object], "threadNotifications": [Map], "threadTimelineSetsPromise": null

Check failure on line 2690 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node latest)

Room › threads › Redactions to reactions in threads do not decrement the length

expect(received).toHaveLength(expected) Expected length: 2 Received length: 0 Received object: {"_currentUserParticipated": false, "_events": {"Room.timeline": [Function forSource], "Room.timelineReset": [Function forSource], "Thread.delete": [Function forSource], "Thread.newReply": [Function forSource], "Thread.update": [Array]}, "_eventsCount": 5, "_maxListeners": undefined, "client": {"_events": [Object], "_eventsCount": 3, "_maxListeners": undefined, "_secretStorage": [ServerSideSecretStorageImpl], "baseUrl": "http://alice.example.com.test.server", "cachedCapabilities": undefined, "callEventHandler": undefined, "canResetTimelineCallback": undefined, "canSupport": [Map], "canSupportVoip": false, "checkTurnServersIntervalID": undefined, "clientOpts": undefined, "clientRunning": false, "clientWellKnown": undefined, "clientWellKnownIntervalID": undefined, "clientWellKnownPromise": undefined, "credentials": [Object], "crypto": undefined, "cryptoBackend": undefined, "cryptoCallbacks": [Object], "cryptoStore": [LocalStorageCryptoStore], "deviceId": "alicedevice", "exportedOlmDeviceToImport": undefined, "fallbackICEServerAllowed": false, "fetchRoomEvent": [Function anonymous], "fixupRoomNotifications": [Function anonymous], "forceTURN": false, "getRoom": [Function anonymous], "groupCallEventHandler": undefined, "http": [MatrixHttpApi], "iceCandidatePoolSize": 0, "idBaseUrl": undefined, "identityServer": undefined, "ignoredInvites": [IgnoredInvites], "isGuestAccount": false, "isVoipWithNoMediaAllowed": false, "mediaHandler": [MediaHandler], "notifTimelineSet": null, "olmVersion": null, "ongoingScrollbacks": [Object], "peekSync": null, "pendingEventEncryption": [Map], "pickleKey": undefined, "pushProcessor": [PushProcessor], "pushRules": undefined, "reEmitter": [TypedReEmitter], "roomList": [RoomList], "roomNameGenerator": undefined, "scheduler": [MatrixScheduler], "serverVersionsPromise": undefined, "sessionId": "SAc19dxRko", "startCallEventHandler": [Function anonymous], "store": [MemoryStore], "supportsCallTransfer": false, "supportsThreads": [Function anonymous], "syncApi": undefined, "syncLeftRoomsPromise": undefined, "syncedLeftRooms": false, "timelineSupport": false, "toDeviceMessageQueue": [ToDeviceMessageQueue], "turnServers": [Array], "turnServersExpiry": 0, "txnCtr": 0, "urlPreviewCache": [Object], "useE2eForGroupCall": true, "usingExternalCrypto": false, "verificationMethods": undefined, Symbol(kCapture): false}, "fetchRootEvent": [Function anonymous], "id": "$153-0.7827705483490643-0.6924546141587979", "initialEventsFetched": true, "lastEvent": [Object], "lastPendingEvent": undefined, "onBeforeRedaction": [Function anonymous], "onEcho": [Function anonymous], "onLocalEcho": [Function anonymous], "onRedaction": [Function anonymous], "onTimelineEvent": [Function anonymous], "pendingEventOrdering": "chronological", "pendingReplyCount": 0, "processRootEvent": [Function anonymous], "reEmitter": {"reEmitters": WeakMap {}, "target": [Circular]}, "receiptCacheByEventId": Map {"$156-0.03367917786873198-0.9047854810000222" => [Array]}, "receipts": Map {"m.read" => [Map]}, "replayEvents": null, "replyCount": 0, "room": {"_events": [Object], "_eventsCount": 3, "_maxListeners": 100, "accountData": [Map], "applyRedaction": [Function anonymous], "blacklistUnverifiedDevices": undefined, "cachedThreadReadReceipts": [Map], "client": [MatrixClient], "currentState": [RoomState], "filteredTimelineSets": [Object], "getTypeWarning": false, "getVersionWarning": false, "lastThread": [Circular], "membersPromise": [Promise], "myUserId": "@alice:bar", "name": "!foo:bar", "normalizedName": "!foo:bar", "notificationCounts": [Object], "oldState": [RoomState], "oldestThreadedReceiptTs": Infinity, "opts": [Object], "pendingEventList": undefined, "polls": [Map], "reEmitter": [TypedReEmitter], "receiptCacheByEventId": [Map], "receipts": [Map], "relations": [RelationsContainer], "roomId": "!foo:bar", "selfMembership": undefined, "summary": null, "summaryHeroes": null, "tags": [Object], "threadNotifications": [Map], "threadTimelineSetsPromise": null,
expect(thread.replyToEvent.getId()).toBe(threadResponse2.getId());

const threadResponse2ReactionRedaction = mkRedaction(threadResponse2Reaction);
Expand Down Expand Up @@ -2727,7 +2727,7 @@
const thread = await prom;
await emitPromise(room, ThreadEvent.Update);

expect(thread).toHaveLength(2);

Check failure on line 2730 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node 18)

Room › threads › should not decrement the length when the thread root is redacted

expect(received).toHaveLength(expected) Expected length: 2 Received length: 0 Received object: {"_currentUserParticipated": false, "_events": {"Room.timeline": [Function forSource], "Room.timelineReset": [Function forSource], "Thread.delete": [Function forSource], "Thread.newReply": [Function forSource], "Thread.update": [Array]}, "_eventsCount": 5, "_maxListeners": undefined, "client": {"_events": [Object], "_eventsCount": 3, "_maxListeners": undefined, "_secretStorage": [ServerSideSecretStorageImpl], "baseUrl": "http://alice.example.com.test.server", "cachedCapabilities": undefined, "callEventHandler": undefined, "canResetTimelineCallback": undefined, "canSupport": [Map], "canSupportVoip": false, "checkTurnServersIntervalID": undefined, "clientOpts": undefined, "clientRunning": false, "clientWellKnown": undefined, "clientWellKnownIntervalID": undefined, "clientWellKnownPromise": undefined, "credentials": [Object], "crypto": undefined, "cryptoBackend": undefined, "cryptoCallbacks": [Object], "cryptoStore": [LocalStorageCryptoStore], "deviceId": "alicedevice", "exportedOlmDeviceToImport": undefined, "fallbackICEServerAllowed": false, "fetchRoomEvent": [Function anonymous], "fixupRoomNotifications": [Function anonymous], "forceTURN": false, "getRoom": [Function anonymous], "groupCallEventHandler": undefined, "http": [MatrixHttpApi], "iceCandidatePoolSize": 0, "idBaseUrl": undefined, "identityServer": undefined, "ignoredInvites": [IgnoredInvites], "isGuestAccount": false, "isVoipWithNoMediaAllowed": false, "mediaHandler": [MediaHandler], "notifTimelineSet": null, "olmVersion": null, "ongoingScrollbacks": [Object], "peekSync": null, "pendingEventEncryption": [Map], "pickleKey": undefined, "pushProcessor": [PushProcessor], "pushRules": undefined, "reEmitter": [TypedReEmitter], "roomList": [RoomList], "roomNameGenerator": undefined, "scheduler": [MatrixScheduler], "serverVersionsPromise": undefined, "sessionId": "JWKcLI0Dem", "startCallEventHandler": [Function anonymous], "store": [MemoryStore], "supportsCallTransfer": false, "supportsThreads": [Function anonymous], "syncApi": undefined, "syncLeftRoomsPromise": undefined, "syncedLeftRooms": false, "timelineSupport": false, "toDeviceMessageQueue": [ToDeviceMessageQueue], "turnServers": [Array], "turnServersExpiry": 0, "txnCtr": 0, "urlPreviewCache": [Object], "useE2eForGroupCall": true, "usingExternalCrypto": false, "verificationMethods": undefined, Symbol(kCapture): false}, "fetchRootEvent": [Function anonymous], "id": "$157-0.30632566048200194-0.6117123222460161", "initialEventsFetched": true, "lastEvent": [Object], "lastPendingEvent": undefined, "onBeforeRedaction": [Function anonymous], "onEcho": [Function anonymous], "onLocalEcho": [Function anonymous], "onRedaction": [Function anonymous], "onTimelineEvent": [Function anonymous], "pendingEventOrdering": "chronological", "pendingReplyCount": 0, "processRootEvent": [Function anonymous], "reEmitter": {"reEmitters": WeakMap {}, "target": [Circular]}, "receiptCacheByEventId": Map {"$160-0.192476567818735-0.20993818597030622" => [Array]}, "receipts": Map {"m.read" => [Map]}, "replayEvents": null, "replyCount": 0, "room": {"_events": [Object], "_eventsCount": 3, "_maxListeners": 100, "accountData": [Map], "applyRedaction": [Function anonymous], "blacklistUnverifiedDevices": undefined, "cachedThreadReadReceipts": [Map], "client": [MatrixClient], "currentState": [RoomState], "filteredTimelineSets": [Object], "getTypeWarning": false, "getVersionWarning": false, "lastThread": [Circular], "membersPromise": [Promise], "myUserId": "@alice:bar", "name": "!foo:bar", "normalizedName": "!foo:bar", "notificationCounts": [Object], "oldState": [RoomState], "oldestThreadedReceiptTs": Infinity, "opts": [Object], "pendingEventList": undefined, "polls": [Map], "reEmitter": [TypedReEmitter], "receiptCacheByEventId": [Map], "receipts": [Map], "relations": [RelationsContainer], "roomId": "!foo:bar", "selfMembership": undefined, "summary": null, "summaryHeroes": null, "tags": [Object], "threadNotifications": [Map], "threadTimelineSetsPromise": null,

Check failure on line 2730 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node latest)

Room › threads › should not decrement the length when the thread root is redacted

expect(received).toHaveLength(expected) Expected length: 2 Received length: 0 Received object: {"_currentUserParticipated": false, "_events": {"Room.timeline": [Function forSource], "Room.timelineReset": [Function forSource], "Thread.delete": [Function forSource], "Thread.newReply": [Function forSource], "Thread.update": [Array]}, "_eventsCount": 5, "_maxListeners": undefined, "client": {"_events": [Object], "_eventsCount": 3, "_maxListeners": undefined, "_secretStorage": [ServerSideSecretStorageImpl], "baseUrl": "http://alice.example.com.test.server", "cachedCapabilities": undefined, "callEventHandler": undefined, "canResetTimelineCallback": undefined, "canSupport": [Map], "canSupportVoip": false, "checkTurnServersIntervalID": undefined, "clientOpts": undefined, "clientRunning": false, "clientWellKnown": undefined, "clientWellKnownIntervalID": undefined, "clientWellKnownPromise": undefined, "credentials": [Object], "crypto": undefined, "cryptoBackend": undefined, "cryptoCallbacks": [Object], "cryptoStore": [LocalStorageCryptoStore], "deviceId": "alicedevice", "exportedOlmDeviceToImport": undefined, "fallbackICEServerAllowed": false, "fetchRoomEvent": [Function anonymous], "fixupRoomNotifications": [Function anonymous], "forceTURN": false, "getRoom": [Function anonymous], "groupCallEventHandler": undefined, "http": [MatrixHttpApi], "iceCandidatePoolSize": 0, "idBaseUrl": undefined, "identityServer": undefined, "ignoredInvites": [IgnoredInvites], "isGuestAccount": false, "isVoipWithNoMediaAllowed": false, "mediaHandler": [MediaHandler], "notifTimelineSet": null, "olmVersion": null, "ongoingScrollbacks": [Object], "peekSync": null, "pendingEventEncryption": [Map], "pickleKey": undefined, "pushProcessor": [PushProcessor], "pushRules": undefined, "reEmitter": [TypedReEmitter], "roomList": [RoomList], "roomNameGenerator": undefined, "scheduler": [MatrixScheduler], "serverVersionsPromise": undefined, "sessionId": "aMn8CDYM37", "startCallEventHandler": [Function anonymous], "store": [MemoryStore], "supportsCallTransfer": false, "supportsThreads": [Function anonymous], "syncApi": undefined, "syncLeftRoomsPromise": undefined, "syncedLeftRooms": false, "timelineSupport": false, "toDeviceMessageQueue": [ToDeviceMessageQueue], "turnServers": [Array], "turnServersExpiry": 0, "txnCtr": 0, "urlPreviewCache": [Object], "useE2eForGroupCall": true, "usingExternalCrypto": false, "verificationMethods": undefined, Symbol(kCapture): false}, "fetchRootEvent": [Function anonymous], "id": "$157-0.18719829669608545-0.4919075558124464", "initialEventsFetched": true, "lastEvent": [Object], "lastPendingEvent": undefined, "onBeforeRedaction": [Function anonymous], "onEcho": [Function anonymous], "onLocalEcho": [Function anonymous], "onRedaction": [Function anonymous], "onTimelineEvent": [Function anonymous], "pendingEventOrdering": "chronological", "pendingReplyCount": 0, "processRootEvent": [Function anonymous], "reEmitter": {"reEmitters": WeakMap {}, "target": [Circular]}, "receiptCacheByEventId": Map {"$160-0.2255233305072777-0.4995820583202373" => [Array]}, "receipts": Map {"m.read" => [Map]}, "replayEvents": null, "replyCount": 0, "room": {"_events": [Object], "_eventsCount": 3, "_maxListeners": 100, "accountData": [Map], "applyRedaction": [Function anonymous], "blacklistUnverifiedDevices": undefined, "cachedThreadReadReceipts": [Map], "client": [MatrixClient], "currentState": [RoomState], "filteredTimelineSets": [Object], "getTypeWarning": false, "getVersionWarning": false, "lastThread": [Circular], "membersPromise": [Promise], "myUserId": "@alice:bar", "name": "!foo:bar", "normalizedName": "!foo:bar", "notificationCounts": [Object], "oldState": [RoomState], "oldestThreadedReceiptTs": Infinity, "opts": [Object], "pendingEventList": undefined, "polls": [Map], "reEmitter": [TypedReEmitter], "receiptCacheByEventId": [Map], "receipts": [Map], "relations": [RelationsContainer], "roomId": "!foo:bar", "selfMembership": undefined, "summary": null, "summaryHeroes": null, "tags": [Object], "threadNotifications": [Map], "threadTimelineSetsPromise": null,
expect(thread.replyToEvent.getId()).toBe(threadResponse2.getId());

prom = emitPromise(room, ThreadEvent.Update);
Expand Down Expand Up @@ -2791,7 +2791,7 @@

expect(thread.initialEventsFetched).toBeTruthy();
await room.addLiveEvents([threadResponse2]);
expect(thread).toHaveLength(2);

Check failure on line 2794 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node 18)

Room › threads › Redacting the lastEvent finds a new lastEvent

expect(received).toHaveLength(expected) Expected length: 2 Received length: 0 Received object: {"_currentUserParticipated": false, "_events": {"Room.timeline": [Function forSource], "Room.timelineReset": [Function forSource], "Thread.delete": [Function forSource], "Thread.newReply": [Function forSource], "Thread.update": [Array]}, "_eventsCount": 5, "_maxListeners": undefined, "client": {"_events": [Object], "_eventsCount": 3, "_maxListeners": undefined, "_secretStorage": [ServerSideSecretStorageImpl], "baseUrl": "http://alice.example.com.test.server", "cachedCapabilities": undefined, "callEventHandler": undefined, "canResetTimelineCallback": undefined, "canSupport": [Map], "canSupportVoip": false, "checkTurnServersIntervalID": undefined, "clientOpts": undefined, "clientRunning": false, "clientWellKnown": undefined, "clientWellKnownIntervalID": undefined, "clientWellKnownPromise": undefined, "createThreadListMessagesRequest": [Function anonymous], "credentials": [Object], "crypto": undefined, "cryptoBackend": undefined, "cryptoCallbacks": [Object], "cryptoStore": [LocalStorageCryptoStore], "deviceId": "alicedevice", "exportedOlmDeviceToImport": undefined, "fallbackICEServerAllowed": false, "fetchRelations": [Function anonymous], "fetchRoomEvent": [Function anonymous], "fixupRoomNotifications": [Function anonymous], "forceTURN": false, "getRoom": [Function anonymous], "groupCallEventHandler": undefined, "http": [MatrixHttpApi], "iceCandidatePoolSize": 0, "idBaseUrl": undefined, "identityServer": undefined, "ignoredInvites": [IgnoredInvites], "isGuestAccount": false, "isVoipWithNoMediaAllowed": false, "mediaHandler": [MediaHandler], "notifTimelineSet": null, "olmVersion": null, "ongoingScrollbacks": [Object], "peekSync": null, "pendingEventEncryption": [Map], "pickleKey": undefined, "pushProcessor": [PushProcessor], "pushRules": undefined, "reEmitter": [TypedReEmitter], "roomList": [RoomList], "roomNameGenerator": undefined, "scheduler": [MatrixScheduler], "serverVersionsPromise": undefined, "sessionId": "Xd83Pq5RNY", "startCallEventHandler": [Function anonymous], "store": [MemoryStore], "supportsCallTransfer": false, "supportsThreads": [Function anonymous], "syncApi": undefined, "syncLeftRoomsPromise": undefined, "syncedLeftRooms": false, "timelineSupport": false, "toDeviceMessageQueue": [ToDeviceMessageQueue], "turnServers": [Array], "turnServersExpiry": 0, "txnCtr": 0, "urlPreviewCache": [Object], "useE2eForGroupCall": true, "usingExternalCrypto": false, "verificationMethods": undefined, Symbol(kCapture): false}, "fetchRootEvent": [Function anonymous], "id": "$161-0.39957710973121974-0.43803616561487924", "initialEventsFetched": true, "lastEvent": [Object], "lastPendingEvent": undefined, "onBeforeRedaction": [Function anonymous], "onEcho": [Function anonymous], "onLocalEcho": [Function anonymous], "onRedaction": [Function anonymous], "onTimelineEvent": [Function anonymous], "pendingEventOrdering": "chronological", "pendingReplyCount": 0, "processRootEvent": [Function anonymous], "reEmitter": {"reEmitters": WeakMap {}, "target": [Circular]}, "receiptCacheByEventId": Map {"$163-0.6462511654700678-0.8702291733685885" => [Array]}, "receipts": Map {"m.read" => [Map]}, "replayEvents": null, "replyCount": 0, "room": {"_events": [Object], "_eventsCount": 5, "_maxListeners": 100, "accountData": [Map], "applyRedaction": [Function anonymous], "blacklistUnverifiedDevices": undefined, "cachedThreadReadReceipts": [Map], "client": [MatrixClient], "currentState": [RoomState], "filteredTimelineSets": [Object], "getTypeWarning": false, "getVersionWarning": false, "lastThread": [Circular], "membersPromise": [Promise], "myUserId": "@alice:bar", "name": "!foo:bar", "normalizedName": "!foo:bar", "notificationCounts": [Object], "oldState": [RoomState], "oldestThreadedReceiptTs": Infinity, "opts": [Object], "pendingEventList": undefined, "polls": [Map], "reEmitter": [TypedReEmitter], "receiptCacheByEventId": [Map], "receipts": [Map], "relations": [RelationsContainer], "roomId": "!foo:bar", "selfMembership": undefined, "summary": null, "summar

Check failure on line 2794 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node latest)

Room › threads › Redacting the lastEvent finds a new lastEvent

expect(received).toHaveLength(expected) Expected length: 2 Received length: 0 Received object: {"_currentUserParticipated": false, "_events": {"Room.timeline": [Function forSource], "Room.timelineReset": [Function forSource], "Thread.delete": [Function forSource], "Thread.newReply": [Function forSource], "Thread.update": [Array]}, "_eventsCount": 5, "_maxListeners": undefined, "client": {"_events": [Object], "_eventsCount": 3, "_maxListeners": undefined, "_secretStorage": [ServerSideSecretStorageImpl], "baseUrl": "http://alice.example.com.test.server", "cachedCapabilities": undefined, "callEventHandler": undefined, "canResetTimelineCallback": undefined, "canSupport": [Map], "canSupportVoip": false, "checkTurnServersIntervalID": undefined, "clientOpts": undefined, "clientRunning": false, "clientWellKnown": undefined, "clientWellKnownIntervalID": undefined, "clientWellKnownPromise": undefined, "createThreadListMessagesRequest": [Function anonymous], "credentials": [Object], "crypto": undefined, "cryptoBackend": undefined, "cryptoCallbacks": [Object], "cryptoStore": [LocalStorageCryptoStore], "deviceId": "alicedevice", "exportedOlmDeviceToImport": undefined, "fallbackICEServerAllowed": false, "fetchRelations": [Function anonymous], "fetchRoomEvent": [Function anonymous], "fixupRoomNotifications": [Function anonymous], "forceTURN": false, "getRoom": [Function anonymous], "groupCallEventHandler": undefined, "http": [MatrixHttpApi], "iceCandidatePoolSize": 0, "idBaseUrl": undefined, "identityServer": undefined, "ignoredInvites": [IgnoredInvites], "isGuestAccount": false, "isVoipWithNoMediaAllowed": false, "mediaHandler": [MediaHandler], "notifTimelineSet": null, "olmVersion": null, "ongoingScrollbacks": [Object], "peekSync": null, "pendingEventEncryption": [Map], "pickleKey": undefined, "pushProcessor": [PushProcessor], "pushRules": undefined, "reEmitter": [TypedReEmitter], "roomList": [RoomList], "roomNameGenerator": undefined, "scheduler": [MatrixScheduler], "serverVersionsPromise": undefined, "sessionId": "57vriJ2dpb", "startCallEventHandler": [Function anonymous], "store": [MemoryStore], "supportsCallTransfer": false, "supportsThreads": [Function anonymous], "syncApi": undefined, "syncLeftRoomsPromise": undefined, "syncedLeftRooms": false, "timelineSupport": false, "toDeviceMessageQueue": [ToDeviceMessageQueue], "turnServers": [Array], "turnServersExpiry": 0, "txnCtr": 0, "urlPreviewCache": [Object], "useE2eForGroupCall": true, "usingExternalCrypto": false, "verificationMethods": undefined, Symbol(kCapture): false}, "fetchRootEvent": [Function anonymous], "id": "$161-0.3638023351158697-0.18085616221240208", "initialEventsFetched": true, "lastEvent": [Object], "lastPendingEvent": undefined, "onBeforeRedaction": [Function anonymous], "onEcho": [Function anonymous], "onLocalEcho": [Function anonymous], "onRedaction": [Function anonymous], "onTimelineEvent": [Function anonymous], "pendingEventOrdering": "chronological", "pendingReplyCount": 0, "processRootEvent": [Function anonymous], "reEmitter": {"reEmitters": WeakMap {}, "target": [Circular]}, "receiptCacheByEventId": Map {"$163-0.933722142319787-0.841355631537313" => [Array]}, "receipts": Map {"m.read" => [Map]}, "replayEvents": null, "replyCount": 0, "room": {"_events": [Object], "_eventsCount": 5, "_maxListeners": 100, "accountData": [Map], "applyRedaction": [Function anonymous], "blacklistUnverifiedDevices": undefined, "cachedThreadReadReceipts": [Map], "client": [MatrixClient], "currentState": [RoomState], "filteredTimelineSets": [Object], "getTypeWarning": false, "getVersionWarning": false, "lastThread": [Circular], "membersPromise": [Promise], "myUserId": "@alice:bar", "name": "!foo:bar", "normalizedName": "!foo:bar", "notificationCounts": [Object], "oldState": [RoomState], "oldestThreadedReceiptTs": Infinity, "opts": [Object], "pendingEventList": undefined, "polls": [Map], "reEmitter": [TypedReEmitter], "receiptCacheByEventId": [Map], "receipts": [Map], "relations": [RelationsContainer], "roomId": "!foo:bar", "selfMembership": undefined, "summary": null, "summaryHe
expect(thread.replyToEvent!.getId()).toBe(threadResponse2.getId());

room.client.fetchRoomEvent = (eventId: string) =>
Expand Down Expand Up @@ -2969,7 +2969,7 @@
expect(rootRelations![0][1].has(rootReaction)).toBeTruthy();

const responseRelations = thread.timelineSet.relations
.getChildEventsForEvent(threadResponse.getId()!, RelationType.Annotation, EventType.Reaction)!

Check failure on line 2972 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node 18)

Room › eventShouldLiveIn › should aggregate relations in thread event timeline set

TypeError: Cannot read properties of undefined (reading 'getSortedAnnotationsByKey') at Object.<anonymous> (spec/unit/room.spec.ts:2972:110)

Check failure on line 2972 in spec/unit/room.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node latest)

Room › eventShouldLiveIn › should aggregate relations in thread event timeline set

TypeError: Cannot read properties of undefined (reading 'getSortedAnnotationsByKey') at Object.<anonymous> (spec/unit/room.spec.ts:2972:110)
.getSortedAnnotationsByKey();
expect(responseRelations).toHaveLength(1);
expect(responseRelations![0][0]).toEqual(threadReaction.getRelation()!.key);
Expand Down
13 changes: 7 additions & 6 deletions src/models/room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2256,6 +2256,13 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
client: this.client,
pendingEventOrdering: this.opts.pendingEventOrdering,
receipts: this.cachedThreadReadReceipts.get(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, and pass
// the event through this.
events,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding events here (to Thread#replayEvents) means that Thread.constructor inserts these correctly regardless of async ordering; previously:

  1. addLiveEvents called with multiple thread events
  2. Thread.constructor is called using the thread root, starts async work...
  3. the original addLiveEvents continues and tries to add the thread responses to the newly-created (but not fully initialized) Thread; fails check in Thread#addEvent where this.initialEventsFetched, so fails to add events to timeline
  4. continuing Thread.constructor async: updateThreadMetadata is called, and tries to get initial fetch of events. somehow this doesn't work – I forget now how (sorry, writing these notes a few days after investigating...)

});

// All read receipts should now come down from sync, we do not need to keep
Expand All @@ -2267,12 +2274,6 @@ export class Room extends ReadReceipt<RoomEmittedEvents, RoomEventHandlerMap> {
// eventtimeline sometimes looks up thread information via the room.
this.threads.set(thread.id, thread);

// 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,
// and pass the event through this.
thread.addEvents(events, false);

this.reEmitter.reEmit(thread, [
ThreadEvent.Delete,
ThreadEvent.Update,
Expand Down
9 changes: 9 additions & 0 deletions src/models/thread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ interface IThreadOpts {
client: MatrixClient;
pendingEventOrdering?: PendingEventOrdering;
receipts?: CachedReceiptStructure[];
events?: MatrixEvent[];
}

export enum FeatureSupport {
Expand Down Expand Up @@ -139,6 +140,8 @@ export class Thread extends ReadReceipt<ThreadEmittedEvents, ThreadEventHandlerM

this.processReceipts(opts.receipts);

this.replayEvents = opts.events ?? [];

// 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();
Expand Down Expand Up @@ -310,6 +313,11 @@ export class Thread extends ReadReceipt<ThreadEmittedEvents, ThreadEventHandlerM
const lastReply = this.lastReply();
const isNewestReply = !lastReply || event.localTimestamp >= lastReply!.localTimestamp;

if (isNewestReply) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workaround for not refetching the thread root (on refetch, we'd get the latest reply event ID in the event's content)

const mapper = this.client.getEventMapper();
this.lastEvent = mapper(event.getEffectiveEvent());
}

// Add all incoming events to the thread's timeline set when there's no server support
if (!Thread.hasServerSideSupport) {
// all the relevant membership info to hydrate events with a sender
Expand All @@ -321,6 +329,7 @@ export class Thread extends ReadReceipt<ThreadEmittedEvents, ThreadEventHandlerM
this.client.decryptEventIfNeeded(event, {});
} else if (!toStartOfTimeline && this.initialEventsFetched && isNewestReply) {
this.addEventToTimeline(event, false);
// TODO: This is another async call without awaiting
this.fetchEditsWhereNeeded(event);
} else if (event.isRelation(RelationType.Annotation) || event.isRelation(RelationType.Replace)) {
if (!this.initialEventsFetched) {
Expand Down
Loading