7 #include <QHttpMultiPart>
8 #include <QNetworkReply>
9 #include <QNetworkRequest>
10 #include <QScopedPointer>
11 #include <QScopedPointerDeleteLater>
13 #include <QStringBuilder>
27 using namespace swift::misc::db;
28 using namespace swift::misc::network;
29 using namespace swift::misc::simulation;
34 CDatabaseWriter::CDatabaseWriter(
const network::CUrl &baseUrl, QObject *parent)
35 : QObject(parent), m_modelPublishUrl(
CDatabaseWriter::getModelPublishUrl(baseUrl)),
49 if (m_shutdown || !
sApp)
55 if (this->isModelReplyOverdue())
57 const bool killed = this->killPendingModelReply();
67 if (m_pendingModelPublishReply)
73 const bool compress = models.
size() > 3;
74 QHttpMultiPart *multiPart =
new QHttpMultiPart(QHttpMultiPart::FormDataType,
this);
79 QUrl url(m_modelPublishUrl.
toQUrl());
81 QNetworkRequest request(url);
82 const QByteArray eInfo = extraInfo.toLatin1();
83 request.setRawHeader(QByteArray(
"swift-extrainfo"), eInfo);
85 m_pendingModelPublishReply =
86 sApp->
postToNetwork(request, logId, multiPart, {
this, &CDatabaseWriter::postedModelsResponse });
87 m_modelReplyPendingSince = QDateTime::currentMSecsSinceEpoch();
94 if (m_shutdown || !
sApp)
107 const bool compress = json.size() > 2048;
108 QHttpMultiPart *multiPart =
new QHttpMultiPart(QHttpMultiPart::FormDataType,
this);
117 QUrl url(m_autoPublishUrl.
toQUrl());
122 QNetworkRequest request(url);
124 m_pendingAutoPublishReply =
125 sApp->
postToNetwork(request, logId, multiPart, {
this, &CDatabaseWriter::postedAutoPublishResponse });
126 m_autoPublishReplyPendingSince = QDateTime::currentMSecsSinceEpoch();
133 this->killPendingModelReply();
138 static const QString n(
"Database writer");
148 void CDatabaseWriter::postedModelsResponse(QNetworkReply *nwReplyPtr)
150 QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
151 if (m_shutdown || !
sApp)
157 m_pendingModelPublishReply =
nullptr;
158 const QUrl url(nwReply->url());
159 const QString urlString(url.toString());
160 if (nwReply->error() == QNetworkReply::NoError)
162 const QString responseData(nwReply->readAll().trimmed());
164 if (responseData.isEmpty())
176 const bool sendingSuccessful =
177 parseSwiftPublishResponse(responseData, modelsPublished, modelsSkipped, msgs, directWrite);
180 emit this->
publishedModels(modelsPublished, modelsSkipped, msgs, sendingSuccessful, directWrite);
187 const QString error = nwReply->errorString();
195 void CDatabaseWriter::postedAutoPublishResponse(QNetworkReply *nwReplyPtr)
198 QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> nwReply(nwReplyPtr);
199 if (m_shutdown || !
sApp)
205 m_pendingAutoPublishReply =
nullptr;
206 const QUrl url(nwReply->url());
207 const QString urlString(url.toString());
208 const QString responseData(nwReply->readAll().trimmed());
209 const QString error = nwReply->errorString();
213 const bool ok = CDatastoreUtility::parseAutoPublishResponse(responseData, msgs);
215 if (nwReply->error() == QNetworkReply::NoError)
224 bool CDatabaseWriter::killPendingModelReply()
226 if (!m_pendingModelPublishReply) {
return false; }
227 m_pendingModelPublishReply->abort();
228 m_pendingModelPublishReply =
nullptr;
229 m_modelReplyPendingSince = -1;
233 bool CDatabaseWriter::isModelReplyOverdue()
const
235 if (m_modelReplyPendingSince < 0 || !m_pendingModelPublishReply) {
return false; }
236 const qint64 ms = QDateTime::currentMSecsSinceEpoch() - m_modelReplyPendingSince;
245 CUrl CDatabaseWriter::getAutoPublishUrl(
const CUrl &baseUrl)
250 QList<QByteArray> CDatabaseWriter::splitData(
const QByteArray &data,
int size)
252 if (data.size() <= size) {
return QList<QByteArray>({ data }); }
253 int pos = 0, arrsize = data.size();
254 QList<QByteArray> arrays;
255 while (pos < arrsize)
257 const QByteArray arr = data.mid(pos, size);
264 bool CDatabaseWriter::parseSwiftPublishResponse(
const QString &jsonResponse,
CAircraftModelList &publishedModels,
270 if (jsonResponse.isEmpty())
273 u
"Empty JSON data for published models"));
277 const QJsonDocument jsonDoc(QJsonDocument::fromJson(jsonResponse.toUtf8()));
280 if (jsonDoc.isArray())
288 if (!jsonDoc.isObject())
290 const QString phpError(CNetworkUtils::removeHtmlPartsFromPhpErrorMessage(jsonResponse));
297 QJsonObject json(jsonDoc.object());
298 bool hasData =
false;
299 if (json.contains(
"msgs"))
301 const QJsonValue msgJson(json.take(
"msgs"));
311 if (json.contains(
"directWrite"))
313 const QJsonValue dw(json.take(
"directWrite"));
314 directWrite = dw.toBool(
false);
317 if (json.contains(
"publishedModels"))
319 const QJsonValue publishedJson(json.take(
"publishedModels"));
328 if (json.contains(
"skippedModels"))
330 const QJsonValue skippedJson(json.take(
"skippedModels"));
342 u
"Received response, but no JSON data"));
SWIFT_CORE_EXPORT swift::core::CApplication * sApp
Single instance of application object.
data::CGlobalSetup getGlobalSetup() const
Global setup.
QNetworkReply * postToNetwork(const QNetworkRequest &request, int logId, const QByteArray &data, const CallbackSlot &callback)
Post to network.
bool dbDebugFlag() const
Debug flag.
static QHttpPart getMultipartWithDebugFlag()
Multipart with DEBUG FLAG for server.
static const QUrlQuery & getCompressedQuery()
Mark as compressed.
static int fillInMissingAircraftAndLiveryEntities(swift::misc::simulation::CAircraftModelList &models)
Fill in missing data if only the id is provided, but no data.
static QHttpPart getJsonTextMultipart(const QJsonObject &json, bool compress)
Multipart for JSON.
swift::misc::CStatusMessageList asyncPublishModel(const swift::misc::simulation::CAircraftModel &model, const QString &extraInfo)
Write model to DB.
const QString & getName()
Name of the worker.
swift::misc::CStatusMessageList asyncPublishModels(const swift::misc::simulation::CAircraftModelList &models, const QString &extraInfo)
Write models to DB.
static const QStringList & getLogCategories()
Log categories.
swift::misc::CStatusMessageList asyncAutoPublish(const swift::misc::simulation::CAutoPublishData &data)
Write auto publis data.
void publishedModelsSimplified(const swift::misc::simulation::CAircraftModelList &modelsPublished, bool directWrite)
Published models, simplified version of publishedModels.
void gracefulShutdown()
Shutdown.
void autoPublished(bool success, const QString &url, const swift::misc::CStatusMessageList &msgs)
Auto publishing completed.
void publishedModels(const swift::misc::simulation::CAircraftModelList &modelsPublished, const swift::misc::simulation::CAircraftModelList &modelsSkipped, const swift::misc::CStatusMessageList &messages, bool sendingSuccessful, bool directWrite)
Published models, the response to.
static const QString & webservice()
Webservice.
static const QString & swiftDbWebservice()
Webservice with swift DB.
A sequence of log categories.
size_type size() const
Returns number of elements in the sequence.
void push_back(const T &value)
Appends an element at the end of the sequence.
bool isEmpty() const
Synonym for empty.
Streamable status message, e.g.
constexpr static auto SeverityError
Status severities.
constexpr static auto SeverityWarning
Status severities.
Status messages, e.g. from Core -> GUI.
static CStatusMessageList fromDatabaseJson(const QJsonArray &array)
From our database JSON format.
static CAircraftModelList fromDatabaseJson(const QJsonArray &array)
From DB JSON with default prefixes.
Value object encapsulating information of a location, kind of simplified CValueObject compliant versi...
CUrl withAppendedPath(const QString &path) const
Append path.
QUrl toQUrl() const
To QUrl.
int addPendingUrl(const CUrl &url, int maxNumber=10)
Add a pending URL.
Aircraft model (used by another pilot, my models on disk)
Value object encapsulating a list of aircraft models.
QJsonArray toDatabaseJson() const
To database JSON.
Objects that can be use for auto-publishing. Auto publishing means we sent those data to the DB.
bool isEmpty() const
Any data?
QString toDatabaseJson() const
Simple database JSON.
Classes interacting with the swift database (aka "datastore").
Free functions in swift::misc.