From e75ce5db54b4bc61087cb65f9e8a37f21780125d Mon Sep 17 00:00:00 2001 From: iProdigy <8106344+iProdigy@users.noreply.github.com> Date: Sat, 16 Dec 2023 06:38:35 -0600 Subject: [PATCH] fix: request more historical messages on wake (#5018) --- CHANGELOG.md | 1 + src/providers/irc/AbstractIrcServer.cpp | 15 ++++++++++- src/providers/irc/AbstractIrcServer.hpp | 1 + src/providers/irc/IrcConnection2.cpp | 1 + src/providers/irc/IrcConnection2.hpp | 3 +++ src/providers/twitch/TwitchChannel.cpp | 32 +++++++++++++----------- src/providers/twitch/TwitchChannel.hpp | 13 +++++++--- src/providers/twitch/TwitchIrcServer.cpp | 1 + 8 files changed, 48 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44a9f740a..439dbda1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,6 +88,7 @@ - Dev: Move `clang-tidy` checker to its own CI job. (#4996) - Dev: Refactored the Image Uploader feature. (#4971) - Dev: Fixed deadlock and use-after-free in tests. (#4981) +- Dev: Load less message history upon reconnects. (#5001, #5018) - Dev: Load less message history upon reconnects. (#5001) - Dev: BREAKING: Replace custom `import()` with normal Lua `require()`. (#5014) - Dev: Fixed most compiler warnings. (#5028) diff --git a/src/providers/irc/AbstractIrcServer.cpp b/src/providers/irc/AbstractIrcServer.cpp index b71bf46d3..f1b069cc4 100644 --- a/src/providers/irc/AbstractIrcServer.cpp +++ b/src/providers/irc/AbstractIrcServer.cpp @@ -85,6 +85,9 @@ AbstractIrcServer::AbstractIrcServer() } this->readConnection_->smartReconnect(); }); + this->connections_.managedConnect(this->readConnection_->heartbeat, [this] { + this->markChannelsConnected(); + }); } void AbstractIrcServer::initializeIrc() @@ -358,11 +361,21 @@ void AbstractIrcServer::onDisconnected() if (auto *channel = dynamic_cast(chan.get())) { - channel->markDisconnectedNow(); + channel->markDisconnected(); } } } +void AbstractIrcServer::markChannelsConnected() +{ + this->forEachChannel([](const ChannelPtr &chan) { + if (auto *channel = dynamic_cast(chan.get())) + { + channel->markConnected(); + } + }); +} + std::shared_ptr AbstractIrcServer::getCustomChannel( const QString &channelName) { diff --git a/src/providers/irc/AbstractIrcServer.hpp b/src/providers/irc/AbstractIrcServer.hpp index 2b29ae43d..10bba1860 100644 --- a/src/providers/irc/AbstractIrcServer.hpp +++ b/src/providers/irc/AbstractIrcServer.hpp @@ -73,6 +73,7 @@ protected: virtual void onReadConnected(IrcConnection *connection); virtual void onWriteConnected(IrcConnection *connection); virtual void onDisconnected(); + void markChannelsConnected(); virtual std::shared_ptr getCustomChannel( const QString &channelName); diff --git a/src/providers/irc/IrcConnection2.cpp b/src/providers/irc/IrcConnection2.cpp index 96619cf82..9f97e6db6 100644 --- a/src/providers/irc/IrcConnection2.cpp +++ b/src/providers/irc/IrcConnection2.cpp @@ -64,6 +64,7 @@ IrcConnection::IrcConnection(QObject *parent) // If we're still receiving messages, all is well this->recentlyReceivedMessage_ = false; this->waitingForPong_ = false; + this->heartbeat.invoke(); return; } diff --git a/src/providers/irc/IrcConnection2.hpp b/src/providers/irc/IrcConnection2.hpp index 4c76161b8..150793ec8 100644 --- a/src/providers/irc/IrcConnection2.hpp +++ b/src/providers/irc/IrcConnection2.hpp @@ -19,6 +19,9 @@ public: // receiver to trigger a reconnect, if desired pajlada::Signals::Signal connectionLost; + // Signal to indicate the connection is still healthy + pajlada::Signals::NoArgSignal heartbeat; + // Request a reconnect with a minimum interval between attempts. // This won't violate RECONNECT_MIN_INTERVAL void smartReconnect(); diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 4652f44fe..ba25e6f79 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -103,10 +103,11 @@ TwitchChannel::TwitchChannel(const QString &name) // We can safely ignore this signal connection this has no external dependencies - once the signal // is destroyed, it will no longer be able to fire std::ignore = this->joined.connect([this]() { - if (this->disconnectedAt_.has_value()) + if (this->disconnected_) { this->loadRecentMessagesReconnect(); - this->disconnectedAt_ = std::nullopt; + this->lastConnectedAt_ = std::chrono::system_clock::now(); + this->disconnected_ = false; } }); @@ -731,6 +732,8 @@ void TwitchChannel::setRoomId(const QString &id) *this->roomID_.access() = id; this->roomIdChanged(); this->loadRecentMessages(); + this->disconnected_ = false; + this->lastConnectedAt_ = std::chrono::system_clock::now(); } } @@ -1105,7 +1108,15 @@ bool TwitchChannel::setLive(bool newLiveStatus) return true; } -void TwitchChannel::markDisconnectedNow() +void TwitchChannel::markConnected() +{ + if (this->lastConnectedAt_.has_value() && !this->disconnected_) + { + this->lastConnectedAt_ = std::chrono::system_clock::now(); + } +} + +void TwitchChannel::markDisconnected() { if (this->roomId().isEmpty()) { @@ -1113,14 +1124,7 @@ void TwitchChannel::markDisconnectedNow() return; } - if (this->disconnectedAt_.has_value()) - { - // don't overwrite prior timestamp since - // a reconnection hasn't happened yet - return; - } - - this->disconnectedAt_ = std::chrono::system_clock::now(); + this->disconnected_ = true; } void TwitchChannel::loadRecentMessages() @@ -1194,14 +1198,14 @@ void TwitchChannel::loadRecentMessagesReconnect() const auto now = std::chrono::system_clock::now(); int limit = getSettings()->twitchMessageHistoryLimit.getValue(); - if (this->disconnectedAt_.has_value()) + if (this->lastConnectedAt_.has_value()) { // calculate how many messages could have occured // while we were not connected to the channel // assuming a maximum of 10 messages per second const auto secondsSinceDisconnect = std::chrono::duration_cast( - now - this->disconnectedAt_.value()) + now - this->lastConnectedAt_.value()) .count(); limit = std::min(static_cast(secondsSinceDisconnect + 1) * 10, limit); @@ -1233,7 +1237,7 @@ void TwitchChannel::loadRecentMessagesReconnect() tc->loadingRecentMessages_.clear(); }, - limit, this->disconnectedAt_, now, true); + limit, this->lastConnectedAt_, now, true); } void TwitchChannel::refreshPubSub() diff --git a/src/providers/twitch/TwitchChannel.hpp b/src/providers/twitch/TwitchChannel.hpp index 5b1d628a6..772ec5f62 100644 --- a/src/providers/twitch/TwitchChannel.hpp +++ b/src/providers/twitch/TwitchChannel.hpp @@ -137,10 +137,14 @@ public: SharedAccessGuard accessStreamStatus() const; /** - * Records the current timestamp the channel was disconnected. - * This can be used to calculate the time spent disconnected after a successful reconnect + * Records that the channel is no longer joined. */ - void markDisconnectedNow(); + void markDisconnected(); + + /** + * Records that the channel's read connection is healthy. + */ + void markConnected(); // Emotes std::optional bttvEmote(const EmoteName &name) const; @@ -364,8 +368,9 @@ private: int chatterCount_{}; UniqueAccess streamStatus_; UniqueAccess roomModes_; + bool disconnected_{}; std::optional> - disconnectedAt_{}; + lastConnectedAt_{}; std::atomic_flag loadingRecentMessages_ = ATOMIC_FLAG_INIT; std::unordered_map> threads_; diff --git a/src/providers/twitch/TwitchIrcServer.cpp b/src/providers/twitch/TwitchIrcServer.cpp index 5982b893d..84be99831 100644 --- a/src/providers/twitch/TwitchIrcServer.cpp +++ b/src/providers/twitch/TwitchIrcServer.cpp @@ -220,6 +220,7 @@ void TwitchIrcServer::readConnectionMessageReceived( { this->addGlobalSystemMessage( "Twitch Servers requested us to reconnect, reconnecting"); + this->markChannelsConnected(); this->connect(); } else if (command == "GLOBALUSERSTATE")