bug fixes and depliyment
This commit is contained in:
+77
-5
@@ -4,6 +4,7 @@
|
||||
#include <QJsonValue>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QTemporaryFile>
|
||||
#include <QWebSocket>
|
||||
#include <QWebSocketProtocol>
|
||||
|
||||
@@ -314,6 +315,7 @@ void SyncSession::startSync(const QString &direction)
|
||||
m_completed = 0;
|
||||
m_failed = 0;
|
||||
m_active = true;
|
||||
qInfo().noquote() << u"Synchronization started: %1, %2 asset(s)"_s.arg(direction).arg(m_total);
|
||||
send({{u"type"_s, u"sync-status"_s},
|
||||
{u"stage"_s, u"started"_s},
|
||||
{u"direction"_s, direction},
|
||||
@@ -344,6 +346,10 @@ void SyncSession::startNextTransfer()
|
||||
|
||||
const TransferSpec &transfer = m_queue.front();
|
||||
const quint64 serial = ++m_transferSerial;
|
||||
qInfo().noquote() << u"Transfer %1/%2 started: %3 (%4)"_s
|
||||
.arg(m_completed + m_failed + 1)
|
||||
.arg(m_total)
|
||||
.arg(transfer.asset.fileName, transfer.direction);
|
||||
send({{u"type"_s, u"asset-status"_s},
|
||||
{u"stage"_s, u"downloading"_s},
|
||||
{u"direction"_s, transfer.direction},
|
||||
@@ -353,8 +359,14 @@ void SyncSession::startNextTransfer()
|
||||
{u"message"_s, u"Downloading original"_s}});
|
||||
|
||||
m_progressTimer.restart();
|
||||
m_temporaryFile = new QTemporaryFile{u"/tmp/immich-sync-XXXXXX"_s, this};
|
||||
if (!m_temporaryFile->open())
|
||||
{
|
||||
finishTransfer(serial, false, u"Unable to create a temporary transfer file"_s);
|
||||
return;
|
||||
}
|
||||
m_download = transfer.source->download(transfer.asset);
|
||||
connect(m_download, &QNetworkReply::metaDataChanged, this, [this, serial] { beginUpload(serial); });
|
||||
connect(m_download, &QNetworkReply::readyRead, this, [this, serial] { storeDownloadedData(serial); });
|
||||
connect(m_download, &QNetworkReply::downloadProgress, this, [this, serial](qint64 received, qint64 total) {
|
||||
if (serial == m_transferSerial)
|
||||
{
|
||||
@@ -366,19 +378,50 @@ void SyncSession::startNextTransfer()
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!storeDownloadedData(serial))
|
||||
{
|
||||
return;
|
||||
}
|
||||
const int status = m_download->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (m_download->error() != QNetworkReply::NoError || status < 200 || status >= 300)
|
||||
{
|
||||
finishTransfer(serial, false, u"Download failed: %1"_s.arg(m_download->errorString()));
|
||||
return;
|
||||
}
|
||||
if (!m_temporaryFile->flush() || !m_temporaryFile->seek(0))
|
||||
{
|
||||
finishTransfer(serial, false, u"Unable to rewind the temporary transfer file"_s);
|
||||
return;
|
||||
}
|
||||
beginUpload(serial);
|
||||
});
|
||||
}
|
||||
|
||||
bool SyncSession::storeDownloadedData(quint64 serial)
|
||||
{
|
||||
if (serial != m_transferSerial || !m_download || !m_temporaryFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
while (m_download->bytesAvailable() > 0)
|
||||
{
|
||||
const QByteArray chunk = m_download->read(1024 * 1024);
|
||||
if (chunk.isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (m_temporaryFile->write(chunk) != chunk.size())
|
||||
{
|
||||
finishTransfer(serial, false, u"Unable to write the temporary transfer file"_s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SyncSession::beginUpload(quint64 serial)
|
||||
{
|
||||
if (serial != m_transferSerial || !m_download || m_upload)
|
||||
if (serial != m_transferSerial || !m_download || !m_temporaryFile || m_upload)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -387,22 +430,36 @@ void SyncSession::beginUpload(quint64 serial)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const TransferSpec &transfer = m_queue.front();
|
||||
m_download->deleteLater();
|
||||
m_download = nullptr;
|
||||
m_multipart = new QHttpMultiPart{QHttpMultiPart::FormDataType};
|
||||
m_upload = transfer.destination->upload(transfer.asset, m_download, m_multipart);
|
||||
m_upload = transfer.destination->upload(transfer.asset, m_temporaryFile, m_multipart);
|
||||
m_multipart->setParent(m_upload);
|
||||
m_uploadCompleteNotified = false;
|
||||
send({{u"type"_s, u"asset-status"_s},
|
||||
{u"stage"_s, u"uploading"_s},
|
||||
{u"direction"_s, transfer.direction},
|
||||
{u"fileName"_s, transfer.asset.fileName},
|
||||
{u"current"_s, static_cast<qint64>(m_completed + m_failed + 1)},
|
||||
{u"total"_s, static_cast<qint64>(m_total)},
|
||||
{u"message"_s, u"Streaming into destination"_s}});
|
||||
{u"message"_s, u"Uploading original to destination"_s}});
|
||||
connect(m_upload, &QNetworkReply::uploadProgress, this, [this, serial](qint64 sent, qint64 total) {
|
||||
if (serial == m_transferSerial)
|
||||
{
|
||||
sendProgress(u"uploading"_s, sent, total);
|
||||
if (total > 0 && sent >= total && !m_uploadCompleteNotified && !m_queue.isEmpty())
|
||||
{
|
||||
m_uploadCompleteNotified = true;
|
||||
const TransferSpec ¤tTransfer = m_queue.front();
|
||||
send({{u"type"_s, u"asset-status"_s},
|
||||
{u"stage"_s, u"processing"_s},
|
||||
{u"direction"_s, currentTransfer.direction},
|
||||
{u"fileName"_s, currentTransfer.asset.fileName},
|
||||
{u"current"_s, static_cast<qint64>(m_completed + m_failed + 1)},
|
||||
{u"total"_s, static_cast<qint64>(m_total)},
|
||||
{u"message"_s, u"Destination Immich is processing the asset"_s}});
|
||||
}
|
||||
}
|
||||
});
|
||||
connect(m_upload, &QNetworkReply::finished, this, [this, serial] {
|
||||
@@ -433,6 +490,8 @@ void SyncSession::finishTransfer(quint64 serial, bool success, const QString &me
|
||||
}
|
||||
++m_transferSerial;
|
||||
const TransferSpec transfer = m_queue.takeFirst();
|
||||
qInfo().noquote() << u"Transfer finished: %1 (%2): %3"_s.arg(transfer.asset.fileName,
|
||||
success ? u"success"_s : u"failed"_s, message);
|
||||
if (success)
|
||||
{
|
||||
++m_completed;
|
||||
@@ -470,6 +529,12 @@ void SyncSession::finishTransfer(quint64 serial, bool success, const QString &me
|
||||
m_upload = nullptr;
|
||||
m_download = nullptr;
|
||||
m_multipart = nullptr;
|
||||
m_uploadCompleteNotified = false;
|
||||
if (m_temporaryFile)
|
||||
{
|
||||
m_temporaryFile->deleteLater();
|
||||
m_temporaryFile = nullptr;
|
||||
}
|
||||
startNextTransfer();
|
||||
}
|
||||
|
||||
@@ -514,8 +579,15 @@ void SyncSession::abort()
|
||||
m_upload = nullptr;
|
||||
m_download = nullptr;
|
||||
m_multipart = nullptr;
|
||||
m_uploadCompleteNotified = false;
|
||||
if (m_temporaryFile)
|
||||
{
|
||||
m_temporaryFile->deleteLater();
|
||||
m_temporaryFile = nullptr;
|
||||
}
|
||||
if (wasActive)
|
||||
{
|
||||
qInfo() << "Synchronization aborted because its WebSocket disconnected";
|
||||
send({{u"type"_s, u"sync-status"_s},
|
||||
{u"stage"_s, u"aborted"_s},
|
||||
{u"message"_s, u"Synchronization and network transfers were aborted"_s}});
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
class QHttpMultiPart;
|
||||
class QNetworkReply;
|
||||
class QTemporaryFile;
|
||||
class QWebSocket;
|
||||
|
||||
class SyncSession final : public QObject {
|
||||
@@ -44,6 +45,7 @@ class SyncSession final : public QObject {
|
||||
void sendInspection();
|
||||
void startSync(const QString &direction);
|
||||
void startNextTransfer();
|
||||
bool storeDownloadedData(quint64 serial);
|
||||
void beginUpload(quint64 serial);
|
||||
void finishTransfer(quint64 serial, bool success, const QString &message, const QString &result = {});
|
||||
void finishJob(const QString &reason);
|
||||
@@ -77,5 +79,7 @@ class SyncSession final : public QObject {
|
||||
QNetworkReply *m_download = nullptr;
|
||||
QNetworkReply *m_upload = nullptr;
|
||||
QHttpMultiPart *m_multipart = nullptr;
|
||||
QTemporaryFile *m_temporaryFile = nullptr;
|
||||
bool m_uploadCompleteNotified = false;
|
||||
QElapsedTimer m_progressTimer;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user