Scrobbler: Add extra submit delay on error

Fixes #898
This commit is contained in:
Jonas Kvinge 2022-02-16 17:46:40 +01:00
parent 7c51f04140
commit 7a53ca7f8e
7 changed files with 76 additions and 65 deletions

View File

@ -195,7 +195,7 @@ void AudioScrobbler::Submit() {
for (ScrobblerService *service : scrobbler_services_->List()) {
if (!service->IsEnabled() || !service->IsAuthenticated() || service->IsSubmitted()) continue;
service->DoSubmit();
service->StartSubmit();
}
}

View File

@ -19,6 +19,8 @@
#include "config.h"
#include <algorithm>
#include <QtGlobal>
#include <QDesktopServices>
#include <QVariant>
@ -73,7 +75,8 @@ ListenBrainzScrobbler::ListenBrainzScrobbler(Application *app, QObject *parent)
login_time_(0),
submitted_(false),
scrobbled_(false),
timestamp_(0) {
timestamp_(0),
submit_error_(false) {
refresh_login_timer_.setSingleShot(true);
QObject::connect(&refresh_login_timer_, &QTimer::timeout, this, &ListenBrainzScrobbler::RequestNewAccessToken);
@ -339,7 +342,7 @@ void ListenBrainzScrobbler::AuthenticateReplyFinished(QNetworkReply *reply) {
qLog(Debug) << "ListenBrainz: Authentication was successful, login expires in" << expires_in_;
DoSubmit();
StartSubmit();
}
@ -509,25 +512,22 @@ void ListenBrainzScrobbler::Scrobble(const Song &song) {
if (app_->scrobbler()->IsOffline() || !IsAuthenticated()) return;
if (!submitted_) {
submitted_ = true;
if (app_->scrobbler()->SubmitDelay() <= 0) {
Submit();
}
else if (!timer_submit_.isActive()) {
timer_submit_.setInterval(static_cast<int>(app_->scrobbler()->SubmitDelay() * kMsecPerSec));
timer_submit_.start();
}
}
StartSubmit();
}
void ListenBrainzScrobbler::DoSubmit() {
void ListenBrainzScrobbler::StartSubmit(const bool initial) {
if (!submitted_ && cache_->Count() > 0) {
submitted_ = true;
if (!timer_submit_.isActive()) {
timer_submit_.setInterval(static_cast<int>(app_->scrobbler()->SubmitDelay() * kMsecPerSec));
if (initial && app_->scrobbler()->SubmitDelay() <= 0 && !submit_error_) {
if (timer_submit_.isActive()) {
timer_submit_.stop();
}
Submit();
}
else if (!timer_submit_.isActive()) {
int submit_delay = static_cast<int>(std::max(app_->scrobbler()->SubmitDelay(), submit_error_ ? 30 : 5) * kMsecPerSec);
timer_submit_.setInterval(submit_delay);
timer_submit_.start();
}
}
@ -538,8 +538,6 @@ void ListenBrainzScrobbler::Submit() {
qLog(Debug) << "ListenBrainz: Submitting scrobbles.";
submitted_ = false;
if (!IsEnabled() || !IsAuthenticated() || app_->scrobbler()->IsOffline()) return;
QJsonArray array;
@ -573,6 +571,8 @@ void ListenBrainzScrobbler::Submit() {
if (i <= 0) return;
submitted_ = true;
QJsonObject object;
object.insert("listen_type", "import");
object.insert("payload", array);
@ -591,17 +591,21 @@ void ListenBrainzScrobbler::ScrobbleRequestFinished(QNetworkReply *reply, const
QObject::disconnect(reply, nullptr, this, nullptr);
reply->deleteLater();
submitted_ = false;
QByteArray data = GetReplyData(reply);
if (data.isEmpty()) {
cache_->ClearSent(list);
DoSubmit();
submit_error_ = true;
StartSubmit();
return;
}
QJsonObject json_obj = ExtractJsonObj(data);
if (json_obj.isEmpty()) {
cache_->ClearSent(list);
DoSubmit();
submit_error_ = true;
StartSubmit();
return;
}
@ -609,7 +613,8 @@ void ListenBrainzScrobbler::ScrobbleRequestFinished(QNetworkReply *reply, const
QString error_desc = json_obj["error_description"].toString();
Error(error_desc);
cache_->ClearSent(list);
DoSubmit();
submit_error_ = true;
StartSubmit();
return;
}
@ -619,7 +624,8 @@ void ListenBrainzScrobbler::ScrobbleRequestFinished(QNetworkReply *reply, const
}
cache_->Flush(list);
DoSubmit();
submit_error_ = false;
StartSubmit();
}

View File

@ -89,7 +89,7 @@ class ListenBrainzScrobbler : public ScrobblerService {
void AuthError(const QString &error);
void Error(const QString &error, const QVariant &debug = QVariant()) override;
void RequestAccessToken(const QUrl &redirect_url = QUrl(), const QString &code = QString());
void DoSubmit() override;
void StartSubmit(const bool initial = false) override;
void CheckScrobblePrevSong();
static const char *kOAuthAuthorizeUrl;
@ -118,6 +118,7 @@ class ListenBrainzScrobbler : public ScrobblerService {
quint64 timestamp_;
QTimer refresh_login_timer_;
QTimer timer_submit_;
bool submit_error_;
QList<QNetworkReply*> replies_;

View File

@ -52,7 +52,7 @@ class ScrobblerService : public QObject {
virtual void Love() {}
virtual void Error(const QString &error, const QVariant &debug = QVariant()) = 0;
virtual void DoSubmit() = 0;
virtual void StartSubmit(const bool initial = false) = 0;
virtual void Submitted() = 0;
virtual bool IsSubmitted() const { return false; }

View File

@ -79,7 +79,8 @@ ScrobblingAPI20::ScrobblingAPI20(const QString &name, const QString &settings_gr
subscriber_(false),
submitted_(false),
scrobbled_(false),
timestamp_(0) {
timestamp_(0),
submit_error_(false) {
timer_submit_.setSingleShot(true);
QObject::connect(&timer_submit_, &QTimer::timeout, this, &ScrobblingAPI20::Submit);
@ -345,7 +346,7 @@ void ScrobblingAPI20::AuthenticateReplyFinished(QNetworkReply *reply) {
emit AuthenticationComplete(true);
DoSubmit();
StartSubmit();
}
@ -536,25 +537,22 @@ void ScrobblingAPI20::Scrobble(const Song &song) {
return;
}
if (!submitted_) {
submitted_ = true;
if (!batch_ || app_->scrobbler()->SubmitDelay() <= 0) {
Submit();
}
else if (!timer_submit_.isActive()) {
timer_submit_.setInterval(static_cast<int>(app_->scrobbler()->SubmitDelay() * kMsecPerSec));
timer_submit_.start();
}
}
StartSubmit(true);
}
void ScrobblingAPI20::DoSubmit() {
void ScrobblingAPI20::StartSubmit(const bool initial) {
if (!submitted_ && cache()->Count() > 0) {
submitted_ = true;
if (!timer_submit_.isActive()) {
timer_submit_.setInterval(static_cast<int>(app_->scrobbler()->SubmitDelay() * kMsecPerSec));
if (initial && (!batch_ || app_->scrobbler()->SubmitDelay() <= 0) && !submit_error_) {
if (timer_submit_.isActive()) {
timer_submit_.stop();
}
Submit();
}
else if (!timer_submit_.isActive()) {
int submit_delay = static_cast<int>(std::max(app_->scrobbler()->SubmitDelay(), submit_error_ ? 30 : 5) * kMsecPerSec);
timer_submit_.setInterval(submit_delay);
timer_submit_.start();
}
}
@ -563,8 +561,6 @@ void ScrobblingAPI20::DoSubmit() {
void ScrobblingAPI20::Submit() {
submitted_ = false;
if (!IsEnabled() || !IsAuthenticated() || app_->scrobbler()->IsOffline()) return;
qLog(Debug) << name_ << "Submitting scrobbles.";
@ -601,6 +597,8 @@ void ScrobblingAPI20::Submit() {
if (!batch_ || i <= 0) return;
submitted_ = true;
QNetworkReply *reply = CreateRequest(params);
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, list]() { ScrobbleRequestFinished(reply, list); });
@ -613,17 +611,21 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, const QList<
QObject::disconnect(reply, nullptr, this, nullptr);
reply->deleteLater();
submitted_ = false;
QByteArray data = GetReplyData(reply);
if (data.isEmpty()) {
cache()->ClearSent(list);
DoSubmit();
submit_error_ = true;
StartSubmit();
return;
}
QJsonObject json_obj = ExtractJsonObj(data);
if (json_obj.isEmpty()) {
cache()->ClearSent(list);
DoSubmit();
submit_error_ = true;
StartSubmit();
return;
}
@ -633,52 +635,53 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, const QList<
QString error_reason = QString("%1 (%2)").arg(error_message).arg(error_code);
Error(error_reason);
cache()->ClearSent(list);
DoSubmit();
return;
}
if (!json_obj.contains("scrobbles")) {
Error("Json reply from server is missing scrobbles.", json_obj);
cache()->ClearSent(list);
DoSubmit();
submit_error_ = true;
StartSubmit();
return;
}
cache()->Flush(list);
submit_error_ = false;
if (!json_obj.contains("scrobbles")) {
Error("Json reply from server is missing scrobbles.", json_obj);
StartSubmit();
return;
}
QJsonValue value_scrobbles = json_obj["scrobbles"];
if (!value_scrobbles.isObject()) {
Error("Json scrobbles is not an object.", json_obj);
DoSubmit();
StartSubmit();
return;
}
json_obj = value_scrobbles.toObject();
if (json_obj.isEmpty()) {
Error("Json scrobbles object is empty.", value_scrobbles);
DoSubmit();
StartSubmit();
return;
}
if (!json_obj.contains("@attr") || !json_obj.contains("scrobble")) {
Error("Json scrobbles object is missing values.", json_obj);
DoSubmit();
StartSubmit();
return;
}
QJsonValue value_attr = json_obj["@attr"];
if (!value_attr.isObject()) {
Error("Json scrobbles attr is not an object.", value_attr);
DoSubmit();
StartSubmit();
return;
}
QJsonObject obj_attr = value_attr.toObject();
if (obj_attr.isEmpty()) {
Error("Json scrobbles attr is empty.", value_attr);
DoSubmit();
StartSubmit();
return;
}
if (!obj_attr.contains("accepted") || !obj_attr.contains("ignored")) {
Error("Json scrobbles attr is missing values.", obj_attr);
DoSubmit();
StartSubmit();
return;
}
int accepted = obj_attr["accepted"].toInt();
@ -693,7 +696,7 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, const QList<
QJsonObject obj_scrobble = value_scrobble.toObject();
if (obj_scrobble.isEmpty()) {
Error("Json scrobbles scrobble object is empty.", obj_scrobble);
DoSubmit();
StartSubmit();
return;
}
array_scrobble.append(obj_scrobble);
@ -702,13 +705,13 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, const QList<
array_scrobble = value_scrobble.toArray();
if (array_scrobble.isEmpty()) {
Error("Json scrobbles scrobble array is empty.", value_scrobble);
DoSubmit();
StartSubmit();
return;
}
}
else {
Error("Json scrobbles scrobble is not an object or array.", value_scrobble);
DoSubmit();
StartSubmit();
return;
}
@ -774,7 +777,7 @@ void ScrobblingAPI20::ScrobbleRequestFinished(QNetworkReply *reply, const QList<
}
DoSubmit();
StartSubmit();
}

View File

@ -130,7 +130,7 @@ class ScrobblingAPI20 : public ScrobblerService {
void SendSingleScrobble(ScrobblerCacheItemPtr item);
void Error(const QString &error, const QVariant &debug = QVariant()) override;
static QString ErrorString(const ScrobbleErrorCode error);
void DoSubmit() override;
void StartSubmit(const bool initial = false) override;
void CheckScrobblePrevSong();
QString name_;
@ -154,6 +154,7 @@ class ScrobblingAPI20 : public ScrobblerService {
Song song_playing_;
bool scrobbled_;
quint64 timestamp_;
bool submit_error_;
QTimer timer_submit_;

View File

@ -54,7 +54,7 @@ class SubsonicScrobbler : public ScrobblerService {
void Scrobble(const Song &song) override;
void Error(const QString &error, const QVariant &debug = QVariant()) override;
void DoSubmit() override {}
void StartSubmit(const bool initial = false) override { Q_UNUSED(initial) }
void Submitted() override { submitted_ = true; }
bool IsSubmitted() const override { return submitted_; }