diff options
author | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2018-01-25 14:06:28 +0900 |
---|---|---|
committer | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2018-01-25 14:06:28 +0900 |
commit | d11b0af7b4a6c572409c0ac979c99a02bfb14761 (patch) | |
tree | bc84cab57d4548c3a43716c247f8064f2d5b4801 | |
parent | 80f75c9b5c6642e8c02e626f991e2ed620a2dc4f (diff) | |
download | libquotient-d11b0af7b4a6c572409c0ac979c99a02bfb14761.tar.gz libquotient-d11b0af7b4a6c572409c0ac979c99a02bfb14761.zip |
Connection: intercept late-coming /sync response on a just forgotten room
Closes #160.
-rw-r--r-- | connection.cpp | 24 |
1 files 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<QPair<QString, bool>, Room*> roomMap; - QVector<QString> justForgottenRoomIds; + QVector<QString> roomIdsToForget; QHash<QString, User*> 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); } |