[Client] Bound stale-membership room join heal to one attempt

The RespContextError heal (leave + rejoin) previously recurred
unconditionally, so a server that kept returning RespContextError for a
reason other than stale membership would loop forever. Track room ids
that already received a heal and surface the error dialog after one
attempt instead of retrying indefinitely.
This commit is contained in:
Lukas Brübach 2026-09-07 09:00:52 +02:00
parent ffc938c977
commit b98d725bc7
2 changed files with 19 additions and 1 deletions

View file

@ -229,6 +229,7 @@ void TabServer::joinRoomFinished(const Response &r,
switch (r.response_code()) {
case Response::RespOk:
healedRoomJoins.remove(roomId);
break;
case Response::RespNameNotFound:
if (setCurrent) {
@ -238,10 +239,24 @@ void TabServer::joinRoomFinished(const Response &r,
emit roomJoinFailed(roomId);
return;
case Response::RespContextError:
if (healedRoomJoins.contains(roomId)) {
// A stale-membership heal was already attempted once; if the server still
// rejects the join there is nothing left to do client-side, so surface it.
if (setCurrent) {
QMessageBox::critical(
this, tr("Error"),
tr("The server thinks you are in the server room but your client is unable to display it. "
"Try restarting your client."));
}
emit roomJoinFailed(roomId);
return;
}
// The server already had us registered in the room even though no tab was open,
// usually because two join attempts for the same room overlapped. Leaving and
// rejoining makes the server reply with a fresh RespOk so the tab is displayed
// without requiring a client restart.
// without requiring a client restart. This is attempted only once: if the server
// keeps replying with RespContextError we must not loop forever.
healedRoomJoins.insert(roomId);
leaveAndRejoinRoom(roomId, setCurrent);
return;
case Response::RespUserLevelTooLow:

View file

@ -11,6 +11,7 @@
#include <QGroupBox>
#include <QMap>
#include <QSet>
#include <QTextBrowser>
#include <QTreeWidget>
@ -67,6 +68,8 @@ private:
bool shouldEmitUpdate = false;
/** Room ids with a join command in flight, mapped to whether the tab should be focused once it opens. */
QMap<int, bool> pendingRoomJoins;
/** Room ids for which a stale-membership heal (leave + rejoin) has already been attempted. */
QSet<int> healedRoomJoins;
public:
TabServer(TabSupervisor *_tabSupervisor, AbstractClient *_client);