-
-
Notifications
You must be signed in to change notification settings - Fork 455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ensure live status requests are always batched #4713
Changes from all commits
644093d
69f6a21
204d18e
6620e76
5a11d80
3145eab
f456690
f17dc43
2c2545f
b0a186c
22e6a29
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,190 @@ | ||||||
#include "controllers/twitch/LiveController.hpp" | ||||||
|
||||||
#include "common/QLogging.hpp" | ||||||
#include "providers/twitch/api/Helix.hpp" | ||||||
#include "providers/twitch/TwitchChannel.hpp" | ||||||
#include "util/Helpers.hpp" | ||||||
|
||||||
#include <QDebug> | ||||||
|
||||||
namespace { | ||||||
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) | ||||||
const auto &LOG = chatterinoTwitchLiveController; | ||||||
|
||||||
} // namespace | ||||||
|
||||||
namespace chatterino { | ||||||
|
||||||
TwitchLiveController::TwitchLiveController() | ||||||
{ | ||||||
QObject::connect(&this->refreshTimer, &QTimer::timeout, [this] { | ||||||
this->request(); | ||||||
}); | ||||||
this->refreshTimer.start(TwitchLiveController::REFRESH_INTERVAL); | ||||||
|
||||||
QObject::connect(&this->immediateRequestTimer, &QTimer::timeout, [this] { | ||||||
QStringList channelIDs; | ||||||
|
||||||
{ | ||||||
std::unique_lock immediateRequestsLock( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'immediateRequestsLock' of type 'std::unique_lock' (aka 'std::unique_lockstd::mutex') can be declared 'const' [misc-const-correctness]
Suggested change
|
||||||
this->immediateRequestsMutex); | ||||||
for (const auto &channelID : this->immediateRequests) | ||||||
{ | ||||||
channelIDs.append(channelID); | ||||||
} | ||||||
this->immediateRequests.clear(); | ||||||
} | ||||||
|
||||||
if (channelIDs.isEmpty()) | ||||||
{ | ||||||
return; | ||||||
} | ||||||
|
||||||
this->request(channelIDs); | ||||||
}); | ||||||
this->immediateRequestTimer.start( | ||||||
TwitchLiveController::IMMEDIATE_REQUEST_INTERVAL); | ||||||
} | ||||||
|
||||||
void TwitchLiveController::add(const std::shared_ptr<TwitchChannel> &newChannel) | ||||||
{ | ||||||
assert(newChannel != nullptr); | ||||||
|
||||||
const auto channelID = newChannel->roomId(); | ||||||
assert(!channelID.isEmpty()); | ||||||
|
||||||
{ | ||||||
std::unique_lock lock(this->channelsMutex); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'lock' of type 'std::unique_lock<shared_mutex>' (aka 'std::unique_lockstd::shared_mutex') can be declared 'const' [misc-const-correctness]
Suggested change
|
||||||
this->channels[channelID] = newChannel; | ||||||
} | ||||||
|
||||||
{ | ||||||
std::unique_lock immediateRequestsLock(this->immediateRequestsMutex); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'immediateRequestsLock' of type 'std::unique_lock' (aka 'std::unique_lockstd::mutex') can be declared 'const' [misc-const-correctness]
Suggested change
|
||||||
this->immediateRequests.emplace(channelID); | ||||||
} | ||||||
} | ||||||
|
||||||
void TwitchLiveController::request(std::optional<QStringList> optChannelIDs) | ||||||
{ | ||||||
QStringList channelIDs; | ||||||
|
||||||
if (optChannelIDs) | ||||||
{ | ||||||
channelIDs = *optChannelIDs; | ||||||
} | ||||||
else | ||||||
{ | ||||||
std::shared_lock lock(this->channelsMutex); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'lock' of type 'std::shared_lock<shared_mutex>' (aka 'std::shared_lockstd::shared_mutex') can be declared 'const' [misc-const-correctness]
Suggested change
|
||||||
|
||||||
for (const auto &channelList : this->channels) | ||||||
{ | ||||||
channelIDs.append(channelList.first); | ||||||
} | ||||||
} | ||||||
|
||||||
if (channelIDs.isEmpty()) | ||||||
{ | ||||||
return; | ||||||
} | ||||||
|
||||||
auto batches = | ||||||
splitListIntoBatches(channelIDs, TwitchLiveController::BATCH_SIZE); | ||||||
|
||||||
qCDebug(LOG) << "Make" << batches.size() << "requests"; | ||||||
|
||||||
for (const auto &batch : batches) | ||||||
{ | ||||||
// TODO: Explore making this concurrent | ||||||
getHelix()->fetchStreams( | ||||||
batch, {}, | ||||||
[this, batch{batch}](const auto &streams) { | ||||||
std::unordered_map<QString, std::optional<HelixStream>> results; | ||||||
|
||||||
for (const auto &channelID : batch) | ||||||
{ | ||||||
results[channelID] = std::nullopt; | ||||||
} | ||||||
|
||||||
for (const auto &stream : streams) | ||||||
{ | ||||||
results[stream.userId] = stream; | ||||||
} | ||||||
|
||||||
QStringList deadChannels; | ||||||
|
||||||
{ | ||||||
std::shared_lock lock(this->channelsMutex); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'lock' of type 'std::shared_lock<shared_mutex>' (aka 'std::shared_lockstd::shared_mutex') can be declared 'const' [misc-const-correctness]
Suggested change
|
||||||
for (const auto &result : results) | ||||||
{ | ||||||
auto it = this->channels.find(result.first); | ||||||
if (it != channels.end()) | ||||||
{ | ||||||
if (auto channel = it->second.lock(); channel) | ||||||
{ | ||||||
channel->updateStreamStatus(result.second); | ||||||
} | ||||||
else | ||||||
{ | ||||||
deadChannels.append(result.first); | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
if (!deadChannels.isEmpty()) | ||||||
{ | ||||||
std::unique_lock lock(this->channelsMutex); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'lock' of type 'std::unique_lock<shared_mutex>' (aka 'std::unique_lockstd::shared_mutex') can be declared 'const' [misc-const-correctness]
Suggested change
|
||||||
for (const auto &deadChannel : deadChannels) | ||||||
{ | ||||||
this->channels.erase(deadChannel); | ||||||
} | ||||||
} | ||||||
}, | ||||||
[] { | ||||||
qCWarning(LOG) << "Failed stream check request"; | ||||||
}, | ||||||
[] {}); | ||||||
|
||||||
// TODO: Explore making this concurrent | ||||||
getHelix()->fetchChannels( | ||||||
batch, | ||||||
[this, batch{batch}](const auto &helixChannels) { | ||||||
QStringList deadChannels; | ||||||
|
||||||
{ | ||||||
std::shared_lock lock(this->channelsMutex); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'lock' of type 'std::shared_lock<shared_mutex>' (aka 'std::shared_lockstd::shared_mutex') can be declared 'const' [misc-const-correctness]
Suggested change
|
||||||
for (const auto &helixChannel : helixChannels) | ||||||
{ | ||||||
auto it = this->channels.find(helixChannel.userId); | ||||||
if (it != this->channels.end()) | ||||||
{ | ||||||
if (auto channel = it->second.lock(); channel) | ||||||
{ | ||||||
channel->updateStreamTitle(helixChannel.title); | ||||||
channel->updateDisplayName(helixChannel.name); | ||||||
} | ||||||
else | ||||||
{ | ||||||
deadChannels.append(helixChannel.userId); | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
if (!deadChannels.isEmpty()) | ||||||
{ | ||||||
std::unique_lock lock(this->channelsMutex); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'lock' of type 'std::unique_lock<shared_mutex>' (aka 'std::unique_lockstd::shared_mutex') can be declared 'const' [misc-const-correctness]
Suggested change
|
||||||
for (const auto &deadChannel : deadChannels) | ||||||
{ | ||||||
this->channels.erase(deadChannel); | ||||||
} | ||||||
} | ||||||
}, | ||||||
[] { | ||||||
qCWarning(LOG) << "Failed stream check request"; | ||||||
}); | ||||||
} | ||||||
} | ||||||
|
||||||
} // namespace chatterino |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: invalid case style for function 'MOCK_METHOD' [readability-identifier-naming]