Make sure to handle 429:s (rate limiting) on message redactions and final room leave!

This commit is contained in:
N-Pex 2023-02-08 11:22:12 +01:00
parent 06d023dc7f
commit 434c0fb48c
3 changed files with 65 additions and 27 deletions

View file

@ -89,8 +89,8 @@
"members": "no members | 1 member | {count} members", "members": "no members | 1 member | {count} members",
"leave": "Leave", "leave": "Leave",
"purge_set_room_state": "Setting room state", "purge_set_room_state": "Setting room state",
"purge_redacting_events": "Redacting events", "purge_redacting_events": "Redacting events ({count} of {total})",
"purge_removing_members": "Removing members", "purge_removing_members": "Removing members ({count} of {total})",
"purge_failed": "Failed to purge room!", "purge_failed": "Failed to purge room!",
"room_list_invites": "Invites", "room_list_invites": "Invites",
"room_list_rooms": "Rooms", "room_list_rooms": "Rooms",

View file

@ -1287,6 +1287,10 @@ export default {
restartRRTimer() { restartRRTimer() {
this.stopRRTimer(); this.stopRRTimer();
if (this.$matrix.currentRoomBeingPurged) {
return;
}
let eventIdFirst = null; let eventIdFirst = null;
let eventIdLast = null; let eventIdLast = null;
if (!this.useAudioLayout) { if (!this.useAudioLayout) {

View file

@ -37,6 +37,7 @@ export default {
userDisplayName: null, userDisplayName: null,
userAvatar: null, userAvatar: null,
currentRoom: null, currentRoom: null,
currentRoomBeingPurged: false,
notificationCount: 0, notificationCount: 0,
}; };
}, },
@ -558,6 +559,28 @@ export default {
* @param roomId * @param roomId
*/ */
purgeRoom(roomId, statusCallback) { purgeRoom(roomId, statusCallback) {
this.currentRoomBeingPurged = true;
const sleep = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
const withRetry = (codeBlock) => {
return codeBlock().catch((error) => {
if (error && error.errcode == "M_LIMIT_EXCEEDED") {
var retry = 1000;
if (error.data) {
const retryIn = error.data.retry_after_ms;
retry = Math.max(retry, retryIn ? retryIn : 0);
}
console.log("Rate limited, retry in", retry);
return sleep(retry).then(() => withRetry(codeBlock));
} else {
return Promise.resolve();
}
});
};
const oldGlobalErrorSetting = this.matrixClient.getGlobalErrorOnUnknownDevices(); const oldGlobalErrorSetting = this.matrixClient.getGlobalErrorOnUnknownDevices();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const room = this.getRoom(roomId); const room = this.getRoom(roomId);
@ -613,14 +636,32 @@ export default {
statusCallback(this.$t("room.purge_redacting_events")); statusCallback(this.$t("room.purge_redacting_events"));
// First ignore unknown device errors // First ignore unknown device errors
this.matrixClient.setGlobalErrorOnUnknownDevices(false); this.matrixClient.setGlobalErrorOnUnknownDevices(false);
var redactionPromises = []; const allEvents = timelineWindow.getEvents().filter((event) => {
timelineWindow.getEvents().forEach((event) => { return (
if (!event.isRedacted() && !event.isRedaction() && !event.isState()) { !event.isRedacted() &&
// Redact! !event.isRedaction() &&
redactionPromises.push(this.matrixClient.redactEvent(event.getRoomId(), event.getId())); !event.isState() &&
} (!room.currentState || room.currentState.maySendRedactionForEvent(event, this.currentUserId))
);
}); });
return Promise.all(redactionPromises);
const redactFirstEvent = (events) => {
statusCallback(
this.$t("room.purge_redacting_events", {
count: allEvents.length - events.length + 1,
total: allEvents.length,
})
);
if (events.length == 0) {
return Promise.resolve(true);
}
const event = events[0];
return withRetry(() => this.matrixClient.redactEvent(event.getRoomId(), event.getId())).then(() =>
redactFirstEvent(events.slice(1))
);
};
return redactFirstEvent(allEvents);
}) })
.then(() => { .then(() => {
//console.log("Purge: kick members"); //console.log("Purge: kick members");
@ -629,12 +670,14 @@ export default {
var invited = room.getMembersWithMembership("invite"); var invited = room.getMembersWithMembership("invite");
var allMembers = joined.concat(invited); var allMembers = joined.concat(invited);
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const kickFirstMember = (members) => { const kickFirstMember = (members) => {
//console.log(`Kicking ${members.length} members`); //console.log(`Kicking ${members.length} members`);
statusCallback(
this.$t("room.purge_removing_members", {
count: allMembers.length - members.length + 1,
total: allMembers.length,
})
);
if (members.length == 0) { if (members.length == 0) {
return Promise.resolve(true); return Promise.resolve(true);
} }
@ -644,19 +687,8 @@ export default {
} else { } else {
// Slight pause to avoid rate limiting. // Slight pause to avoid rate limiting.
return sleep(0.1) return sleep(0.1)
.then(() => this.matrixClient.kick(roomId, member.userId, "Room Deleted")) .then(() => withRetry(() => this.matrixClient.kick(roomId, member.userId, "Room Deleted")))
.catch((error) => { .then(() => kickFirstMember(members.slice(1)));
if (error && error.errcode == "M_LIMIT_EXCEEDED") {
var retry = 1000;
if (error.data) {
const retryIn = error.data.retry_after_ms;
retry = Math.max(retry, retryIn ? retryIn : 0);
}
//console.log("Rate limited, retry in", retry);
return sleep(retry).then(() => kickFirstMember(members));
}
})
.finally(() => kickFirstMember(members.slice(1)))
} }
}; };
@ -665,13 +697,15 @@ export default {
.then(() => { .then(() => {
statusCallback(null); statusCallback(null);
this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting); this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting);
return this.leaveRoom(roomId); return withRetry(() => this.leaveRoom(roomId));
}) })
.then(() => { .then(() => {
this.currentRoomBeingPurged = false;
resolve(true); // Done! resolve(true); // Done!
}) })
.catch((err) => { .catch((err) => {
console.error("Error purging room", err); console.error("Error purging room", err);
this.currentRoomBeingPurged = false;
this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting); this.matrixClient.setGlobalErrorOnUnknownDevices(oldGlobalErrorSetting);
reject(err); reject(err);
}); });