Skip to content

Commit

Permalink
Added low priority requests for services so that requests for images …
Browse files Browse the repository at this point in the history
…don't delay more important ones
  • Loading branch information
PhilInTheGaps committed Dec 12, 2023
1 parent 56c5690 commit a439143
Show file tree
Hide file tree
Showing 29 changed files with 368 additions and 166 deletions.
17 changes: 17 additions & 0 deletions src/services/rest/restrequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ class RestRequest
explicit RestRequest(int id, const QNetworkRequest &request, Type type, QByteArray data, QByteArray verb)
: m_id(id), m_type(type), m_request(request), m_data(std::move(data)), m_verb(std::move(verb))
{
if (verb.isEmpty())
{
switch (type)
{
case Type::GET:
m_verb = "GET";
break;
case Type::PUT:
m_verb = "PUT";
break;
case Type::POST:
m_verb = "POST";
break;
default:
break;
}
}
}

[[nodiscard]] auto id() const -> int
Expand Down
33 changes: 26 additions & 7 deletions src/services/rest/restserviceconnector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,23 @@ void RESTServiceConnector::setStatus(Status::Type type, const QString &message)

void RESTServiceConnector::dequeueRequests()
{
qCDebug(m_loggingCategory) << "Dequeueing requests ..." << m_requestQueue.size();
qCDebug(m_loggingCategory) << "Dequeueing requests ..." << m_requestQueueHighPriority.size()
<< m_requestQueueLowPriority.size();

QString reason;
while (canSendRequest(reason) && !m_requestQueue.empty())

while (canSendRequest(reason) && !m_requestQueueHighPriority.empty())
{
auto [reply, request] = std::move(m_requestQueueHighPriority.front());
m_requestQueueHighPriority.pop();

sendRequest(std::move(request), std::move(reply));
}

while (canSendRequest(reason) && !m_requestQueueLowPriority.empty())
{
auto [reply, request] = std::move(m_requestQueue.front());
m_requestQueue.pop();
auto [reply, request] = std::move(m_requestQueueLowPriority.front());
m_requestQueueLowPriority.pop();

sendRequest(std::move(request), std::move(reply));
}
Expand Down Expand Up @@ -148,12 +158,21 @@ auto RESTServiceConnector::canSendRequest(QString &reason) -> bool
return true;
}

auto RESTServiceConnector::enqueueRequest(RestRequest &&request, QPromise<RestReply> &&reply) -> QFuture<RestReply>
auto RESTServiceConnector::enqueueRequest(RestRequest &&request, QPromise<RestReply> &&reply, bool lowPriority)
-> QFuture<RestReply>
{
auto future = reply.future();
request.id(m_nextQueueId);
m_nextQueueId++;
m_requestQueue.emplace(std::move(reply), std::move(request));

if (lowPriority)
{
m_requestQueueLowPriority.emplace(std::move(reply), std::move(request));
}
else
{
m_requestQueueHighPriority.emplace(std::move(reply), std::move(request));
}

// try to dispatch request
dequeueRequests();
Expand Down Expand Up @@ -245,5 +264,5 @@ void RESTServiceConnector::handleRateLimit(std::pair<QPromise<RestReply>, RestRe
}

startCooldown(timeout);
m_requestQueue.push(std::move(pair));
m_requestQueueHighPriority.push(std::move(pair));
}
15 changes: 8 additions & 7 deletions src/services/rest/restserviceconnector.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ class RESTServiceConnector : public QObject
virtual void disconnectService() = 0;
[[nodiscard]] virtual auto isAccessGranted() const -> bool = 0;

virtual auto get(const QNetworkRequest &request, bool isAuthRequired) -> QFuture<RestReply> = 0;
virtual auto put(QNetworkRequest request, const QByteArray &data) -> QFuture<RestReply> = 0;
virtual auto post(QNetworkRequest request, const QByteArray &data) -> QFuture<RestReply> = 0;
virtual auto customRequest(const QNetworkRequest &req, const QByteArray &verb, const QByteArray &data)
-> QFuture<RestReply> = 0;
virtual auto get(const QNetworkRequest &request, bool isAuthRequired, bool lowPriority) -> QFuture<RestReply> = 0;
virtual auto put(QNetworkRequest request, const QByteArray &data, bool lowPriority) -> QFuture<RestReply> = 0;
virtual auto post(QNetworkRequest request, const QByteArray &data, bool lowPriority) -> QFuture<RestReply> = 0;
virtual auto customRequest(const QNetworkRequest &req, const QByteArray &verb, const QByteArray &data,
bool isAuthRequired, bool lowPriority) -> QFuture<RestReply> = 0;

[[nodiscard]] auto networkManager() const -> QNetworkAccessManager *;
void setNetworkManager(QNetworkAccessManager *networkManager);
Expand All @@ -56,7 +56,7 @@ protected slots:

void dequeueRequests();
[[nodiscard]] auto canSendRequest(QString &reason) -> bool;
auto enqueueRequest(RestRequest &&request, QPromise<RestReply> &&reply) -> QFuture<RestReply>;
auto enqueueRequest(RestRequest &&request, QPromise<RestReply> &&reply, bool lowPriority) -> QFuture<RestReply>;
auto markRequestActive(RestRequest &&request, QPromise<RestReply> &&reply) -> QFuture<RestReply>;
virtual void sendRequest(RestRequest &&request, QPromise<RestReply> &&reply) = 0;

Expand Down Expand Up @@ -89,7 +89,8 @@ protected slots:
QDateTime m_tokenExpireTime;

std::unordered_map<int, std::pair<QPromise<RestReply>, RestRequest>> m_activeRequests;
std::queue<std::pair<QPromise<RestReply>, RestRequest>> m_requestQueue;
std::queue<std::pair<QPromise<RestReply>, RestRequest>> m_requestQueueHighPriority;
std::queue<std::pair<QPromise<RestReply>, RestRequest>> m_requestQueueLowPriority;
};

} // namespace Services
21 changes: 13 additions & 8 deletions src/services/rest/restserviceconnectorlocal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,42 +167,47 @@ void RESTServiceConnectorLocal::refreshAccessToken(bool /*updateAuthentication*/
m_o2->refresh();
}

auto RESTServiceConnectorLocal::get(const QNetworkRequest &request, bool isAuthRequired) -> QFuture<RestReply>
auto RESTServiceConnectorLocal::get(const QNetworkRequest &request, bool isAuthRequired, bool lowPriority)
-> QFuture<RestReply>
{
QPromise<RestReply> promise;
promise.start();

RestRequest container(request, RestRequest::Type::GET);
container.isAuthRequired(isAuthRequired);
return enqueueRequest(std::move(container), std::move(promise));
return enqueueRequest(std::move(container), std::move(promise), lowPriority);
}

auto RESTServiceConnectorLocal::put(QNetworkRequest request, const QByteArray &data) -> QFuture<RestReply>
auto RESTServiceConnectorLocal::put(QNetworkRequest request, const QByteArray &data, bool lowPriority)
-> QFuture<RestReply>
{
QPromise<RestReply> promise;
promise.start();

RestRequest container(request, RestRequest::Type::PUT, data);
return enqueueRequest(std::move(container), std::move(promise));
return enqueueRequest(std::move(container), std::move(promise), lowPriority);
}

auto RESTServiceConnectorLocal::post(QNetworkRequest request, const QByteArray &data) -> QFuture<RestReply>
auto RESTServiceConnectorLocal::post(QNetworkRequest request, const QByteArray &data, bool lowPriority)
-> QFuture<RestReply>
{
QPromise<RestReply> promise;
promise.start();

RestRequest container(request, RestRequest::Type::POST, data);
return enqueueRequest(std::move(container), std::move(promise));
return enqueueRequest(std::move(container), std::move(promise), lowPriority);
}

auto RESTServiceConnectorLocal::customRequest(const QNetworkRequest &request, const QByteArray &verb,
const QByteArray &data) -> QFuture<RestReply>
const QByteArray &data, bool isAuthRequired, bool lowPriority)
-> QFuture<RestReply>
{
QPromise<RestReply> promise;
promise.start();

RestRequest container(request, RestRequest::Type::CUSTOM, data, verb);
return enqueueRequest(std::move(container), std::move(promise));
container.isAuthRequired(isAuthRequired);
return enqueueRequest(std::move(container), std::move(promise), lowPriority);
}

auto RESTServiceConnectorLocal::makeRequestor() -> O2Requestor *
Expand Down
10 changes: 5 additions & 5 deletions src/services/rest/restserviceconnectorlocal.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ class RESTServiceConnectorLocal : public RESTServiceConnector
void disconnectService() override;
[[nodiscard]] auto isAccessGranted() const -> bool override;

auto get(const QNetworkRequest &request, bool isAuthRequired) -> QFuture<RestReply> override;
auto put(QNetworkRequest request, const QByteArray &data) -> QFuture<RestReply> override;
auto post(QNetworkRequest request, const QByteArray &data) -> QFuture<RestReply> override;
auto customRequest(const QNetworkRequest &req, const QByteArray &verb, const QByteArray &data)
-> QFuture<RestReply> override;
auto get(const QNetworkRequest &request, bool isAuthRequired, bool lowPriority) -> QFuture<RestReply> override;
auto put(QNetworkRequest request, const QByteArray &data, bool lowPriority) -> QFuture<RestReply> override;
auto post(QNetworkRequest request, const QByteArray &data, bool lowPriority) -> QFuture<RestReply> override;
auto customRequest(const QNetworkRequest &req, const QByteArray &verb, const QByteArray &data, bool isAuthRequired,
bool lowPriority) -> QFuture<RestReply> override;

protected:
O2 *m_o2 = nullptr;
Expand Down
32 changes: 16 additions & 16 deletions src/services/spotify/api/albumapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ AlbumAPI::AlbumAPI(Spotify *parent) : m_spotify(parent)
{
}

auto AlbumAPI::getAlbum(const QString &id) -> QFuture<SpotifyAlbum>
auto AlbumAPI::getAlbum(const QString &id, bool lowPriority) -> QFuture<SpotifyAlbum>
{
if (id.isEmpty())
{
Expand All @@ -30,7 +30,7 @@ auto AlbumAPI::getAlbum(const QString &id) -> QFuture<SpotifyAlbum>
query.addQueryItem(u"market"_s, u"from_token"_s);
url.setQuery(query);

const auto callback = [this](const RestReply &reply) {
const auto callback = [this, lowPriority](const RestReply &reply) {
if (reply.hasError())
{
qCWarning(gmSpotifyAlbums()) << "getAlbum():" << reply.errorText();
Expand All @@ -41,16 +41,16 @@ auto AlbumAPI::getAlbum(const QString &id) -> QFuture<SpotifyAlbum>

if (!album.tracks.next.isEmpty())
{
return getAlbumTracks(std::move(album));
return getAlbumTracks(std::move(album), lowPriority);
}

return QtFuture::makeReadyFuture(album);
};

return m_spotify->get(NetworkUtils::makeJsonRequest(url)).then(callback).unwrap();
return m_spotify->get(NetworkUtils::makeJsonRequest(url), true, lowPriority).then(callback).unwrap();
}

auto AlbumAPI::getAlbumTracks(const QString &id) -> QFuture<SpotifyTrackList>
auto AlbumAPI::getAlbumTracks(const QString &id, bool lowPriority) -> QFuture<SpotifyTrackList>
{
if (id.isEmpty())
{
Expand All @@ -65,7 +65,7 @@ auto AlbumAPI::getAlbumTracks(const QString &id) -> QFuture<SpotifyTrackList>
query.addQueryItem(u"market"_s, u"from_token"_s);
url.setQuery(query);

auto callback = [this](const RestReply &reply) -> QFuture<SpotifyTrackList> {
auto callback = [this, lowPriority](const RestReply &reply) -> QFuture<SpotifyTrackList> {
if (reply.hasError())
{
qCWarning(gmSpotifyAlbums()) << reply.errorText();
Expand All @@ -75,21 +75,21 @@ auto AlbumAPI::getAlbumTracks(const QString &id) -> QFuture<SpotifyTrackList>
auto tracklist = SpotifyTrackList::fromJson(reply.data());
if (!tracklist.next.isEmpty())
{
return getAlbumTracks(std::move(tracklist));
return getAlbumTracks(std::move(tracklist), lowPriority);
}
return QtFuture::makeReadyFuture(tracklist);
};

return m_spotify->get(NetworkUtils::makeJsonRequest(url)).then(callback).unwrap();
return m_spotify->get(NetworkUtils::makeJsonRequest(url), true, lowPriority).then(callback).unwrap();
}

auto AlbumAPI::getAlbumTracks(SpotifyAlbum &&album) -> QFuture<SpotifyAlbum>
auto AlbumAPI::getAlbumTracks(SpotifyAlbum &&album, bool lowPriority) -> QFuture<SpotifyAlbum>
{
if (album.tracks.next.isEmpty()) return QtFuture::makeReadyFuture(album);

const QUrl url(album.tracks.next);

const auto callback = [this, album](const RestReply &reply) mutable {
const auto callback = [this, lowPriority, album = std::move(album)](const RestReply &reply) mutable {
if (reply.hasError())
{
qCWarning(gmSpotifyAlbums()) << reply.errorText();
Expand All @@ -99,19 +99,19 @@ auto AlbumAPI::getAlbumTracks(SpotifyAlbum &&album) -> QFuture<SpotifyAlbum>
album.tracks.append(SpotifyTrackList::fromJson(reply.data()));
if (!album.tracks.next.isEmpty())
{
return getAlbumTracks(std::move(album));
return getAlbumTracks(std::move(album), lowPriority);
}
return QtFuture::makeReadyFuture(album);
};

return m_spotify->get(NetworkUtils::makeJsonRequest(url)).then(callback).unwrap();
return m_spotify->get(NetworkUtils::makeJsonRequest(url), true, lowPriority).then(callback).unwrap();
}

auto AlbumAPI::getAlbumTracks(SpotifyTrackList &&tracklist) -> QFuture<SpotifyTrackList>
auto AlbumAPI::getAlbumTracks(SpotifyTrackList &&tracklist, bool lowPriority) -> QFuture<SpotifyTrackList>
{
const QUrl url(tracklist.next);

const auto callback = [this, tracklist](const RestReply &reply) mutable {
const auto callback = [this, tracklist = std::move(tracklist), lowPriority](const RestReply &reply) mutable {
if (reply.hasError())
{
qCWarning(gmSpotifyAlbums()) << reply.errorText();
Expand All @@ -121,10 +121,10 @@ auto AlbumAPI::getAlbumTracks(SpotifyTrackList &&tracklist) -> QFuture<SpotifyTr
tracklist.append(SpotifyTrackList::fromJson(reply.data()));
if (!tracklist.next.isEmpty())
{
return getAlbumTracks(std::move(tracklist));
return getAlbumTracks(std::move(tracklist), lowPriority);
}
return QtFuture::makeReadyFuture(tracklist);
};

return m_spotify->get(NetworkUtils::makeJsonRequest(url)).then(callback).unwrap();
return m_spotify->get(NetworkUtils::makeJsonRequest(url), true, lowPriority).then(callback).unwrap();
}
8 changes: 4 additions & 4 deletions src/services/spotify/api/albumapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ class AlbumAPI
friend Spotify;

public:
[[nodiscard]] auto getAlbum(const QString &id) -> QFuture<SpotifyAlbum>;
[[nodiscard]] auto getAlbum(const QString &id, bool lowPriority) -> QFuture<SpotifyAlbum>;

[[nodiscard]] auto getAlbumTracks(const QString &id) -> QFuture<SpotifyTrackList>;
[[nodiscard]] auto getAlbumTracks(SpotifyAlbum &&album) -> QFuture<SpotifyAlbum>;
[[nodiscard]] auto getAlbumTracks(SpotifyTrackList &&tracklist) -> QFuture<SpotifyTrackList>;
[[nodiscard]] auto getAlbumTracks(const QString &id, bool lowPriority) -> QFuture<SpotifyTrackList>;
[[nodiscard]] auto getAlbumTracks(SpotifyAlbum &&album, bool lowPriority) -> QFuture<SpotifyAlbum>;
[[nodiscard]] auto getAlbumTracks(SpotifyTrackList &&tracklist, bool lowPriority) -> QFuture<SpotifyTrackList>;

private:
explicit AlbumAPI(Spotify *parent);
Expand Down
Loading

0 comments on commit a439143

Please sign in to comment.