Skip to content

Commit

Permalink
Merge pull request #5036 from nextcloud/feature/improveNetworkErrorHa…
Browse files Browse the repository at this point in the history
…ndling

Feature/improve network error handling
  • Loading branch information
mgallien authored Jun 28, 2023
2 parents a7e10a1 + 033a37e commit 0a65df1
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/gui/accountstate.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class AccountState : public QObject, public QSharedData
{
Q_OBJECT
Q_PROPERTY(AccountPtr account MEMBER _account)
Q_PROPERTY(State state READ state NOTIFY stateChanged)

public:
enum State {
Expand Down
61 changes: 55 additions & 6 deletions src/gui/tray/activitylistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ ActivityListModel::ActivityListModel(AccountState *accountState,
: QAbstractListModel(parent)
, _accountState(accountState)
{
if (_accountState) {
connect(_accountState, &AccountState::stateChanged,
this, &ActivityListModel::accountStateChanged);
_accountStateWasConnected = false;
}
}

QHash<int, QByteArray> ActivityListModel::roleNames() const
Expand Down Expand Up @@ -90,8 +95,17 @@ QHash<int, QByteArray> ActivityListModel::roleNames() const

void ActivityListModel::setAccountState(AccountState *state)
{
if (_accountState == state) {
return;
}

_accountState = state;
Q_EMIT accountStateChanged();
if (_accountState) {
connect(_accountState, &AccountState::stateChanged,
this, &ActivityListModel::accountStateHasChanged);
_accountStateWasConnected = false;
}
}

void ActivityListModel::setCurrentItem(const int currentItem)
Expand Down Expand Up @@ -558,15 +572,50 @@ void ActivityListModel::addEntriesToActivityList(const ActivityList &activityLis
setHasSyncConflicts(conflictsFound);
}

void ActivityListModel::accountStateHasChanged()
{
if (!_accountState) {
return;
}

if (_accountStateWasConnected == _accountState->isConnected()) {
return;
}

if (!_accountState->isConnected()) {
_durationSinceDisconnection.start();
} else {
_durationSinceDisconnection.invalidate();
}

_accountStateWasConnected = _accountState->isConnected();
}

void ActivityListModel::addErrorToActivityList(const Activity &activity, const ErrorType type)
{
qCDebug(lcActivity) << "Error successfully added to the notification list: " << type << activity._message << activity._subject << activity._syncResultStatus << activity._syncFileItemStatus;
auto modifiedActivity = activity;
if (type == ErrorType::NetworkError) {
modifiedActivity._subject = tr("Network error occurred: client will retry syncing.");
auto shouldAddError = false;

switch (type)
{
case ErrorType::NetworkError:
if (_durationSinceDisconnection.isValid() && _durationSinceDisconnection.hasExpired(3 * 60 *1000)) {
shouldAddError = true;
}
break;
case ErrorType::SyncError:
shouldAddError = true;
break;
}

if (shouldAddError) {
qCDebug(lcActivity) << "Error successfully added to the notification list: " << type << activity._message << activity._subject << activity._syncResultStatus << activity._syncFileItemStatus;
auto modifiedActivity = activity;
if (type == ErrorType::NetworkError) {
modifiedActivity._subject = tr("Network error occurred: client will retry syncing.");
}
addEntriesToActivityList({modifiedActivity});
_notificationErrorsLists.prepend(modifiedActivity);
}
addEntriesToActivityList({modifiedActivity});
_notificationErrorsLists.prepend(modifiedActivity);
}

void ActivityListModel::addIgnoredFileToList(const Activity &newActivity)
Expand Down
7 changes: 6 additions & 1 deletion src/gui/tray/activitylistmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public slots:
void slotTriggerDismiss(const int activityIndex);

void addNotificationToActivityList(const OCC::Activity &activity);
void addErrorToActivityList(const OCC::Activity &activity, const ErrorType type);
void addErrorToActivityList(const OCC::Activity &activity, const OCC::ActivityListModel::ErrorType type);
void addIgnoredFileToList(const OCC::Activity &newActivity);
void addSyncFileItemToActivityList(const OCC::Activity &activity);
void removeActivityFromActivityList(int row);
Expand Down Expand Up @@ -163,6 +163,7 @@ protected slots:

private slots:
void addEntriesToActivityList(const OCC::ActivityList &activityList);
void accountStateHasChanged();

private:
static QVariantList convertLinksToMenuEntries(const Activity &activity);
Expand Down Expand Up @@ -209,6 +210,10 @@ private slots:

bool _hasSyncConflicts = false;

bool _accountStateWasConnected = false;

QElapsedTimer _durationSinceDisconnection;

static constexpr quint32 MaxActionButtons = 3;
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/gui/tray/usermodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public slots:
void slotItemCompleted(const QString &folder, const OCC::SyncFileItemPtr &item);
void slotProgressInfo(const QString &folder, const OCC::ProgressInfo &progress);
void slotAddError(const QString &folderAlias, const QString &message, OCC::ErrorCategory category);
void slotAddErrorToGui(const QString &folderAlias, const OCC::SyncFileItem::Status status, const QString &errorMessage, const QString &subject, const ErrorCategory category);
void slotAddErrorToGui(const QString &folderAlias, const OCC::SyncFileItem::Status status, const QString &errorMessage, const QString &subject, const OCC::ErrorCategory category);
void slotNotificationRequestFinished(int statusCode);
void slotNotifyNetworkError(QNetworkReply *reply);
void slotEndNotificationRequest(int replyCode);
Expand Down
2 changes: 1 addition & 1 deletion src/libsync/propagateupload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ void PropagateUploadFileCommon::slotPollFinished()
finalize();
}

void PropagateUploadFileCommon::done(SyncFileItem::Status status, const QString &errorString, const ErrorCategory category)
void PropagateUploadFileCommon::done(const SyncFileItem::Status status, const QString &errorString, const ErrorCategory category)
{
_finished = true;
PropagateItemJob::done(status, errorString, category);
Expand Down
2 changes: 1 addition & 1 deletion src/libsync/propagateupload.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ private slots:
void slotPollFinished();

protected:
void done(SyncFileItem::Status status, const QString &errorString = QString(), const ErrorCategory category = ErrorCategory::NoError) override;
void done(const SyncFileItem::Status status, const QString &errorString = QString(), const ErrorCategory category = ErrorCategory::NoError) override;

/**
* Aborts all running network jobs, except for the ones that mayAbortJob
Expand Down
11 changes: 11 additions & 0 deletions test/testactivitylistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,17 @@ class TestActivityListModel : public QObject
return model;
}

void testActivityAdd(void(OCC::ActivityListModel::*addingMethod)(const OCC::Activity&, OCC::ActivityListModel::ErrorType), OCC::Activity &activity) {
const auto model = testingALM();
QCOMPARE(model->rowCount(), 0);

(model.data()->*addingMethod)(activity, OCC::ActivityListModel::ErrorType::SyncError);
QCOMPARE(model->rowCount(), 1);

const auto index = model->index(0, 0);
QVERIFY(index.isValid());
}

void testActivityAdd(void(OCC::ActivityListModel::*addingMethod)(const OCC::Activity&), OCC::Activity &activity) {
const auto model = testingALM();
QCOMPARE(model->rowCount(), 0);
Expand Down
6 changes: 3 additions & 3 deletions test/testdownload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private slots:
{
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
fakeFolder.syncEngine().setIgnoreHiddenFiles(true);
QSignalSpy completeSpy(&fakeFolder.syncEngine(), &SyncEngine::itemCompleted);
QSignalSpy completeSpy(&fakeFolder.syncEngine(), &OCC::SyncEngine::itemCompleted);
auto size = 30 * 1000 * 1000;
fakeFolder.remoteModifier().insert("A/a0", size);

Expand Down Expand Up @@ -96,7 +96,7 @@ private slots:

FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
fakeFolder.syncEngine().setIgnoreHiddenFiles(true);
QSignalSpy completeSpy(&fakeFolder.syncEngine(), &SyncEngine::itemCompleted);
QSignalSpy completeSpy(&fakeFolder.syncEngine(), &OCC::SyncEngine::itemCompleted);
auto size = 3'500'000;
fakeFolder.remoteModifier().insert("A/broken", size);

Expand Down Expand Up @@ -236,7 +236,7 @@ private slots:
resendActual = 0;
resendExpected = 10;

QSignalSpy completeSpy(&fakeFolder.syncEngine(), &SyncEngine::itemCompleted);
QSignalSpy completeSpy(&fakeFolder.syncEngine(), &OCC::SyncEngine::itemCompleted);
QVERIFY(!fakeFolder.syncOnce());
QCOMPARE(resendActual, 4); // the 4th fails because it only resends 3 times
QCOMPARE(getItem(completeSpy, "A/resendme")->_status, SyncFileItem::NormalError);
Expand Down
2 changes: 1 addition & 1 deletion test/testsyncfilestatustracker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class StatusPushSpy : public QSignalSpy
SyncEngine &_syncEngine;
public:
StatusPushSpy(SyncEngine &syncEngine)
: QSignalSpy(&syncEngine.syncFileStatusTracker(), &SyncFileStatusTracker::fileStatusChanged)
: QSignalSpy(&syncEngine.syncFileStatusTracker(), &OCC::SyncFileStatusTracker::fileStatusChanged)
, _syncEngine(syncEngine)
{ }

Expand Down

0 comments on commit 0a65df1

Please sign in to comment.