From 6ab89ce02e450605cebd432d2113a3115d0cf8c1 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 25 Jan 2018 13:21:44 +0900 Subject: Connection::forgetRoom: Support forgetting invites too Closes #157. --- connection.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/connection.cpp b/connection.cpp index f498f613..e182f9d9 100644 --- a/connection.cpp +++ b/connection.cpp @@ -377,17 +377,19 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) // a ForgetRoomJob is created in advance and can be returned in a probably // not-yet-started state (it will start once /leave completes). auto forgetJob = new ForgetRoomJob(id); - auto joinedRoom = d->roomMap.value({id, false}); - if (joinedRoom && joinedRoom->joinState() == JoinState::Join) + auto room = d->roomMap.value({id, false}); + if (!room) + room = d->roomMap.value({id, true}); + if (room && room->joinState() != JoinState::Leave) { - auto leaveJob = joinedRoom->leaveRoom(); + auto leaveJob = room->leaveRoom(); connect(leaveJob, &BaseJob::success, this, [this, forgetJob] { forgetJob->start(connectionData()); }); connect(leaveJob, &BaseJob::failure, forgetJob, &BaseJob::abandon); } else forgetJob->start(connectionData()); - connect(forgetJob, &BaseJob::success, this, [this, &id] + connect(forgetJob, &BaseJob::success, this, [this, id] { // If the room happens to be in the map (possible in both forms), // delete the found object(s). -- cgit v1.2.3 From 80f75c9b5c6642e8c02e626f991e2ed620a2dc4f Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 25 Jan 2018 14:05:28 +0900 Subject: Connection::provideRoom: assert no empty ids Bonus: slightly more accurate comment in Connection::forgetRoom --- connection.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/connection.cpp b/connection.cpp index e182f9d9..8cdaa3dd 100644 --- a/connection.cpp +++ b/connection.cpp @@ -59,6 +59,7 @@ class Connection::Private // separately so we should, e.g., keep objects for Invite and // Leave state of the same room. QHash, Room*> roomMap; + QVector justForgottenRoomIds; QHash userMap; QString userId; @@ -383,16 +384,17 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) if (room && room->joinState() != JoinState::Leave) { auto leaveJob = room->leaveRoom(); - connect(leaveJob, &BaseJob::success, - this, [this, forgetJob] { forgetJob->start(connectionData()); }); + connect(leaveJob, &BaseJob::success, this, [this, forgetJob, id] { + forgetJob->start(connectionData()); + d->justForgottenRoomIds.push_back(id); + }); connect(leaveJob, &BaseJob::failure, forgetJob, &BaseJob::abandon); } else forgetJob->start(connectionData()); connect(forgetJob, &BaseJob::success, this, [this, id] { - // If the room happens to be in the map (possible in both forms), - // delete the found object(s). + // If the room is in the map (possibly in both forms), delete all forms. for (auto f: {false, true}) if (auto r = d->roomMap.take({ id, f })) { @@ -479,11 +481,7 @@ const ConnectionData* Connection::connectionData() const Room* Connection::provideRoom(const QString& id, JoinState joinState) { // TODO: This whole function is a strong case for a RoomManager class. - if (id.isEmpty()) - { - qCDebug(MAIN) << "Connection::provideRoom() with empty id, doing nothing"; - return nullptr; - } + Q_ASSERT_X(!id.isEmpty(), __FUNCTION__, "Empty room id"); const auto roomKey = qMakePair(id, joinState == JoinState::Invite); auto* room = d->roomMap.value(roomKey, nullptr); -- cgit v1.2.3 From d11b0af7b4a6c572409c0ac979c99a02bfb14761 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Thu, 25 Jan 2018 14:06:28 +0900 Subject: Connection: intercept late-coming /sync response on a just forgotten room Closes #160. --- connection.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/connection.cpp b/connection.cpp index 8cdaa3dd..1e7d1edf 100644 --- a/connection.cpp +++ b/connection.cpp @@ -59,7 +59,7 @@ class Connection::Private // separately so we should, e.g., keep objects for Invite and // Leave state of the same room. QHash, Room*> roomMap; - QVector justForgottenRoomIds; + QVector roomIdsToForget; QHash userMap; QString userId; @@ -257,6 +257,21 @@ void Connection::onSyncSuccess(SyncData &&data) { d->data->setLastEvent(data.nextBatch()); for( auto&& roomData: data.takeRoomData() ) { + const auto forgetIdx = d->roomIdsToForget.indexOf(roomData.roomId); + if (forgetIdx != -1) + { + d->roomIdsToForget.removeAt(forgetIdx); + if (roomData.joinState == JoinState::Leave) + { + qDebug(MAIN) << "Room" << roomData.roomId + << "has been forgotten, ignoring /sync response for it"; + continue; + } + qWarning(MAIN) << "Room" << roomData.roomId + << "has just been forgotten but /sync returned it in" + << toCString(roomData.joinState) + << "state - suspiciously fast turnaround"; + } if ( auto* r = provideRoom(roomData.roomId, roomData.joinState) ) r->updateData(std::move(roomData)); } @@ -384,9 +399,12 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id) if (room && room->joinState() != JoinState::Leave) { auto leaveJob = room->leaveRoom(); - connect(leaveJob, &BaseJob::success, this, [this, forgetJob, id] { + connect(leaveJob, &BaseJob::success, this, [this, forgetJob, room] { forgetJob->start(connectionData()); - d->justForgottenRoomIds.push_back(id); + // If the matching /sync response hasn't arrived yet, mark the room + // for explicit deletion + if (room->joinState() != JoinState::Leave) + d->roomIdsToForget.push_back(room->id()); }); connect(leaveJob, &BaseJob::failure, forgetJob, &BaseJob::abandon); } -- cgit v1.2.3