perf: query fewer historical messages on reconnects (#5001)
Co-authored-by: Ruben Anders <ruben.anders@robotty.de> Co-authored-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
@@ -18,72 +18,84 @@ namespace chatterino::recentmessages {
|
||||
|
||||
using namespace recentmessages::detail;
|
||||
|
||||
void load(const QString &channelName, std::weak_ptr<Channel> channelPtr,
|
||||
ResultCallback onLoaded, ErrorCallback onError)
|
||||
void load(
|
||||
const QString &channelName, std::weak_ptr<Channel> channelPtr,
|
||||
ResultCallback onLoaded, ErrorCallback onError, const int limit,
|
||||
const std::optional<std::chrono::time_point<std::chrono::system_clock>>
|
||||
after,
|
||||
const std::optional<std::chrono::time_point<std::chrono::system_clock>>
|
||||
before,
|
||||
const bool jitter)
|
||||
{
|
||||
qCDebug(LOG) << "Loading recent messages for" << channelName;
|
||||
|
||||
const auto url = constructRecentMessagesUrl(channelName);
|
||||
const auto url =
|
||||
constructRecentMessagesUrl(channelName, limit, after, before);
|
||||
|
||||
NetworkRequest(url)
|
||||
.onSuccess([channelPtr, onLoaded](const auto &result) {
|
||||
auto shared = channelPtr.lock();
|
||||
if (!shared)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(LOG) << "Successfully loaded recent messages for"
|
||||
<< shared->getName();
|
||||
|
||||
auto root = result.parseJson();
|
||||
auto parsedMessages = parseRecentMessages(root);
|
||||
|
||||
// build the Communi messages into chatterino messages
|
||||
auto builtMessages =
|
||||
buildRecentMessages(parsedMessages, shared.get());
|
||||
|
||||
postToThread([shared = std::move(shared), root = std::move(root),
|
||||
messages = std::move(builtMessages),
|
||||
onLoaded]() mutable {
|
||||
// Notify user about a possible gap in logs if it returned some messages
|
||||
// but isn't currently joined to a channel
|
||||
const auto errorCode = root.value("error_code").toString();
|
||||
if (!errorCode.isEmpty())
|
||||
const long delayMs = jitter ? std::rand() % 100 : 0;
|
||||
QTimer::singleShot(delayMs, [=] {
|
||||
NetworkRequest(url)
|
||||
.onSuccess([channelPtr, onLoaded](const auto &result) {
|
||||
auto shared = channelPtr.lock();
|
||||
if (!shared)
|
||||
{
|
||||
qCDebug(LOG)
|
||||
<< QString("Got error from API: error_code=%1, "
|
||||
"channel=%2")
|
||||
.arg(errorCode, shared->getName());
|
||||
if (errorCode == "channel_not_joined" && !messages.empty())
|
||||
{
|
||||
shared->addMessage(makeSystemMessage(
|
||||
"Message history service recovering, there may "
|
||||
"be gaps in the message history."));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
onLoaded(messages);
|
||||
});
|
||||
})
|
||||
.onError([channelPtr, onError](const NetworkResult &result) {
|
||||
auto shared = channelPtr.lock();
|
||||
if (!shared)
|
||||
{
|
||||
return;
|
||||
}
|
||||
qCDebug(LOG) << "Successfully loaded recent messages for"
|
||||
<< shared->getName();
|
||||
|
||||
qCDebug(LOG) << "Failed to load recent messages for"
|
||||
<< shared->getName();
|
||||
auto root = result.parseJson();
|
||||
auto parsedMessages = parseRecentMessages(root);
|
||||
|
||||
shared->addMessage(makeSystemMessage(
|
||||
QStringLiteral(
|
||||
"Message history service unavailable (Error: %1)")
|
||||
.arg(result.formatError())));
|
||||
// build the Communi messages into chatterino messages
|
||||
auto builtMessages =
|
||||
buildRecentMessages(parsedMessages, shared.get());
|
||||
|
||||
onError();
|
||||
})
|
||||
.execute();
|
||||
postToThread([shared = std::move(shared),
|
||||
root = std::move(root),
|
||||
messages = std::move(builtMessages),
|
||||
onLoaded]() mutable {
|
||||
// Notify user about a possible gap in logs if it returned some messages
|
||||
// but isn't currently joined to a channel
|
||||
const auto errorCode = root.value("error_code").toString();
|
||||
if (!errorCode.isEmpty())
|
||||
{
|
||||
qCDebug(LOG)
|
||||
<< QString("Got error from API: error_code=%1, "
|
||||
"channel=%2")
|
||||
.arg(errorCode, shared->getName());
|
||||
if (errorCode == "channel_not_joined" &&
|
||||
!messages.empty())
|
||||
{
|
||||
shared->addMessage(makeSystemMessage(
|
||||
"Message history service recovering, there may "
|
||||
"be gaps in the message history."));
|
||||
}
|
||||
}
|
||||
|
||||
onLoaded(messages);
|
||||
});
|
||||
})
|
||||
.onError([channelPtr, onError](const NetworkResult &result) {
|
||||
auto shared = channelPtr.lock();
|
||||
if (!shared)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(LOG) << "Failed to load recent messages for"
|
||||
<< shared->getName();
|
||||
|
||||
shared->addMessage(makeSystemMessage(
|
||||
QStringLiteral(
|
||||
"Message history service unavailable (Error: %1)")
|
||||
.arg(result.formatError())));
|
||||
|
||||
onError();
|
||||
})
|
||||
.execute();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace chatterino::recentmessages
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace chatterino {
|
||||
@@ -28,8 +30,16 @@ using ErrorCallback = std::function<void()>;
|
||||
* @param channelPtr Weak pointer to Channel to use to build messages
|
||||
* @param onLoaded Callback taking the built messages as a const std::vector<MessagePtr> &
|
||||
* @param onError Callback called when the network request fails
|
||||
* @param limit Maximum number of messages to query
|
||||
* @param after Only return messages that were received after this timestamp; ignored if `std::nullopt`
|
||||
* @param before Only return messages that were received before this timestamp; ignored if `std::nullopt`
|
||||
* @param jitter Whether to delay the request by a small random duration
|
||||
*/
|
||||
void load(const QString &channelName, std::weak_ptr<Channel> channelPtr,
|
||||
ResultCallback onLoaded, ErrorCallback onError);
|
||||
void load(
|
||||
const QString &channelName, std::weak_ptr<Channel> channelPtr,
|
||||
ResultCallback onLoaded, ErrorCallback onError, int limit,
|
||||
std::optional<std::chrono::time_point<std::chrono::system_clock>> after,
|
||||
std::optional<std::chrono::time_point<std::chrono::system_clock>> before,
|
||||
bool jitter);
|
||||
|
||||
} // namespace chatterino::recentmessages
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "providers/twitch/IrcMessageHandler.hpp"
|
||||
#include "providers/twitch/TwitchChannel.hpp"
|
||||
#include "providers/twitch/TwitchMessageBuilder.hpp"
|
||||
#include "singletons/Settings.hpp"
|
||||
#include "util/FormatTime.hpp"
|
||||
|
||||
#include <QJsonArray>
|
||||
@@ -94,14 +93,34 @@ std::vector<MessagePtr> buildRecentMessages(
|
||||
|
||||
// Returns the URL to be used for querying the Recent Messages API for the
|
||||
// given channel.
|
||||
QUrl constructRecentMessagesUrl(const QString &name)
|
||||
QUrl constructRecentMessagesUrl(
|
||||
const QString &name, const int limit,
|
||||
const std::optional<std::chrono::time_point<std::chrono::system_clock>>
|
||||
after,
|
||||
const std::optional<std::chrono::time_point<std::chrono::system_clock>>
|
||||
before)
|
||||
{
|
||||
QUrl url(Env::get().recentMessagesApiUrl.arg(name));
|
||||
QUrlQuery urlQuery(url);
|
||||
if (!urlQuery.hasQueryItem("limit"))
|
||||
{
|
||||
urlQuery.addQueryItem("limit", QString::number(limit));
|
||||
}
|
||||
if (after.has_value())
|
||||
{
|
||||
urlQuery.addQueryItem(
|
||||
"limit", QString::number(getSettings()->twitchMessageHistoryLimit));
|
||||
"after", QString::number(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
after->time_since_epoch())
|
||||
.count()));
|
||||
}
|
||||
if (before.has_value())
|
||||
{
|
||||
urlQuery.addQueryItem(
|
||||
"before", QString::number(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
before->time_since_epoch())
|
||||
.count()));
|
||||
}
|
||||
url.setQuery(urlQuery);
|
||||
return url;
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace chatterino::recentmessages::detail {
|
||||
@@ -24,6 +26,9 @@ std::vector<MessagePtr> buildRecentMessages(
|
||||
|
||||
// Returns the URL to be used for querying the Recent Messages API for the
|
||||
// given channel.
|
||||
QUrl constructRecentMessagesUrl(const QString &name);
|
||||
QUrl constructRecentMessagesUrl(
|
||||
const QString &name, int limit,
|
||||
std::optional<std::chrono::time_point<std::chrono::system_clock>> after,
|
||||
std::optional<std::chrono::time_point<std::chrono::system_clock>> before);
|
||||
|
||||
} // namespace chatterino::recentmessages::detail
|
||||
|
||||
Reference in New Issue
Block a user