From acb89d3447dff6cf29f61558629cb1b0d37a1e3d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 3 Sep 2021 12:56:09 +0100 Subject: [PATCH] Serialize and retry mass-leave when leaving space --- src/utils/membership.ts | 25 ++++++++++++++++++------- src/utils/space.tsx | 4 +++- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/utils/membership.ts b/src/utils/membership.ts index f980d1dcd6..1a120e08b3 100644 --- a/src/utils/membership.ts +++ b/src/utils/membership.ts @@ -15,6 +15,8 @@ limitations under the License. */ import { Room } from "matrix-js-sdk/src/models/room"; +import { sleep } from "matrix-js-sdk/src/utils"; + import { MatrixClientPeg } from "../MatrixClientPeg"; import { _t } from "../languageHandler"; import Modal from "../Modal"; @@ -83,9 +85,10 @@ export function isJoinedOrNearlyJoined(membership: string): boolean { return effective === EffectiveMembership.Join || effective === EffectiveMembership.Invite; } -export async function leaveRoomBehaviour(roomId: string) { +export async function leaveRoomBehaviour(roomId: string, retry = true) { + const cli = MatrixClientPeg.get(); let leavingAllVersions = true; - const history = await MatrixClientPeg.get().getRoomUpgradeHistory(roomId); + const history = cli.getRoomUpgradeHistory(roomId); if (history && history.length > 0) { const currentRoom = history[history.length - 1]; if (currentRoom.roomId !== roomId) { @@ -95,20 +98,28 @@ export async function leaveRoomBehaviour(roomId: string) { } } - let results: { [roomId: string]: Error & { errcode: string, message: string } } = {}; + let results: { [roomId: string]: Error & { errcode?: string, message: string, data?: Record } } = {}; if (!leavingAllVersions) { try { - await MatrixClientPeg.get().leave(roomId); + await cli.leave(roomId); } catch (e) { - if (e && e.data && e.data.errcode) { + if (e?.data?.errcode) { const message = e.data.error || _t("Unexpected server error trying to leave the room"); - results[roomId] = Object.assign(new Error(message), { errcode: e.data.errcode }); + results[roomId] = Object.assign(new Error(message), { errcode: e.data.errcode, data: e.data }); } else { results[roomId] = e || new Error("Failed to leave room for unknown causes"); } } } else { - results = await MatrixClientPeg.get().leaveRoomChain(roomId); + results = await cli.leaveRoomChain(roomId, retry); + } + + if (retry) { + const limitExceededError = Object.values(results).find(e => e?.errcode === "M_LIMIT_EXCEEDED"); + if (limitExceededError) { + await sleep(limitExceededError.data.retry_after_ms ?? 100); + return leaveRoomBehaviour(roomId, false); + } } const errors = Object.entries(results).filter(r => !!r[1]); diff --git a/src/utils/space.tsx b/src/utils/space.tsx index c1d8dbfbea..5bbae369e7 100644 --- a/src/utils/space.tsx +++ b/src/utils/space.tsx @@ -162,7 +162,9 @@ export const leaveSpace = (space: Room) => { if (!leave) return; const modal = Modal.createDialog(Spinner, null, "mx_Dialog_spinner"); try { - await Promise.all(rooms.map(r => leaveRoomBehaviour(r.roomId))); + for (const room of rooms) { + await leaveRoomBehaviour(room.roomId); + } await leaveRoomBehaviour(space.roomId); } finally { modal.close();