diff --git a/spec/unit/matrixrtc/MatrixRTCSession.spec.ts b/spec/unit/matrixrtc/MatrixRTCSession.spec.ts index d19038ff25..fab61029bb 100644 --- a/spec/unit/matrixrtc/MatrixRTCSession.spec.ts +++ b/spec/unit/matrixrtc/MatrixRTCSession.spec.ts @@ -46,9 +46,6 @@ describe("MatrixRTCSession", () => { client = new MatrixClient({ baseUrl: "base_url" }); client.getUserId = jest.fn().mockReturnValue("@alice:example.org"); client.getDeviceId = jest.fn().mockReturnValue("AAAAAAA"); - client.doesServerSupportUnstableFeature = jest.fn((feature) => - Promise.resolve(feature === "org.matrix.msc4140"), - ); }); afterEach(() => { @@ -414,6 +411,8 @@ describe("MatrixRTCSession", () => { client._unstable_sendDelayedStateEvent = sendDelayedStateMock; client.sendEvent = sendEventMock; + client._unstable_updateDelayedEvent = jest.fn(); + mockRoom = makeMockRoom([]); sess = MatrixRTCSession.roomSessionForRoom(client, mockRoom); }); @@ -490,6 +489,13 @@ describe("MatrixRTCSession", () => { ); await Promise.race([sentDelayedState, new Promise((resolve) => realSetTimeout(resolve, 500))]); expect(client._unstable_sendDelayedStateEvent).toHaveBeenCalledTimes(1); + + // should have tried updating the delayed leave to test that it wasn't replaced by own state + expect(client._unstable_updateDelayedEvent).toHaveBeenCalledTimes(1); + // should update delayed disconnect + jest.advanceTimersByTime(5000); + expect(client._unstable_updateDelayedEvent).toHaveBeenCalledTimes(2); + jest.useRealTimers(); } diff --git a/src/matrixrtc/MatrixRTCSession.ts b/src/matrixrtc/MatrixRTCSession.ts index a76df9afd4..bb8c033403 100644 --- a/src/matrixrtc/MatrixRTCSession.ts +++ b/src/matrixrtc/MatrixRTCSession.ts @@ -140,6 +140,8 @@ export class MatrixRTCSession extends TypedEventEmitter>(); private lastEncryptionKeyUpdateRequest?: number; + private disconnectDelayId: string | undefined; + // We use this to store the last membership fingerprints we saw, so we can proactively re-send encryption keys // if it looks like a membership has been updated. private lastMembershipFingerprints: Set | undefined; @@ -1011,19 +1013,24 @@ export class MatrixRTCSession extends TypedEventEmitter => { try { // TODO: If delayed event times out, re-join! const res = await this.client._unstable_sendDelayedStateEvent( @@ -1035,12 +1042,63 @@ export class MatrixRTCSession extends TypedEventEmitter this.delayDisconnection(delayId), 5000); + private scheduleDelayDisconnection(): void { + this.memberEventTimeout = setTimeout(this.delayDisconnection, 5000); } - private async delayDisconnection(delayId: string): Promise { + private readonly delayDisconnection = async (): Promise => { try { - await this.client._unstable_updateDelayedEvent(delayId, UpdateDelayedEventAction.Restart); - this.scheduleDelayDisconnection(delayId); + await this.client._unstable_updateDelayedEvent(this.disconnectDelayId!, UpdateDelayedEventAction.Restart); + this.scheduleDelayDisconnection(); } catch (e) { - logger.error("Failed to delay our disconnection event", e); + // TODO: Retry if rate-limited + logger.error("Failed to delay our disconnection event:", e); } - } + }; private stateEventsContainOngoingLegacySession(callMemberEvents: Map | undefined): boolean { if (!callMemberEvents?.size) {