Skip to content

Commit

Permalink
ensure that bulk upload network job errors are handled
Browse files Browse the repository at this point in the history
in case we get a network error during bulk propagator POST network
request, report all files within this upload as files in error that will
then be sent using the plain old WebDAV protocol

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
  • Loading branch information
mgallien committed Feb 10, 2022
1 parent 9eaf12e commit b57be68
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/libsync/bulkpropagatorjob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -407,12 +407,18 @@ void BulkPropagatorJob::slotPutFinished()

slotJobDestroyed(job); // remove it from the _jobs list

const auto jobError = job->reply()->error();

const auto replyData = job->reply()->readAll();
const auto replyJson = QJsonDocument::fromJson(replyData);
const auto fullReplyObject = replyJson.object();

for (const auto &singleFile : _filesToUpload) {
if (!fullReplyObject.contains(singleFile._remotePath)) {
if (jobError != QNetworkReply::NoError) {
singleFile._item->_status = SyncFileItem::NormalError;
abortWithError(singleFile._item, SyncFileItem::NormalError, tr("Network Error: %1").arg(jobError));
}
continue;
}
const auto singleReplyObject = fullReplyObject[singleFile._remotePath].toObject();
Expand Down
51 changes: 51 additions & 0 deletions test/testsyncengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,57 @@ private slots:
QCOMPARE(nPUT, 6);
QCOMPARE(nPOST, 0);
}

/**
* Checks whether subsequent large uploads are skipped after a 507 error
*/
void testNetworkErrorsWithBulkUpload()
{
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ {"bulkupload", "1.0"} } } });

// Disable parallel uploads
SyncOptions syncOptions;
syncOptions._parallelNetworkJobs = 0;
fakeFolder.syncEngine().setSyncOptions(syncOptions);

int nPUT = 0;
int nPOST = 0;
fakeFolder.setServerOverride([&](QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData) -> QNetworkReply * {
auto contentType = request.header(QNetworkRequest::ContentTypeHeader).toString();
if (op == QNetworkAccessManager::PostOperation) {
++nPOST;
if (contentType.startsWith(QStringLiteral("multipart/related; boundary="))) {
return new FakeErrorReply(op, request, this, 400);
}
return nullptr;
} else if (op == QNetworkAccessManager::PutOperation) {
++nPUT;
}
return nullptr;
});

fakeFolder.localModifier().insert("A/big1", 1);
fakeFolder.localModifier().insert("A/big2", 1);
fakeFolder.localModifier().insert("A/big3", 1);
fakeFolder.localModifier().insert("A/big4", 1);
fakeFolder.localModifier().insert("A/big5", 1);
fakeFolder.localModifier().insert("A/big6", 1);
fakeFolder.localModifier().insert("A/big7", 1);
fakeFolder.localModifier().insert("A/big8", 1);
fakeFolder.localModifier().insert("B/big8", 1);

QVERIFY(!fakeFolder.syncOnce());
QCOMPARE(nPUT, 0);
QCOMPARE(nPOST, 1);
nPUT = 0;
nPOST = 0;

QVERIFY(fakeFolder.syncOnce());
QCOMPARE(nPUT, 9);
QCOMPARE(nPOST, 0);
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
}
};

QTEST_GUILESS_MAIN(TestSyncEngine)
Expand Down

0 comments on commit b57be68

Please sign in to comment.