WIP: error handling

This commit is contained in:
Ondřej Fischer 2019-11-27 08:46:47 +01:00
parent a9852b88c1
commit f1f14bfd3e
5 changed files with 76 additions and 34 deletions

View File

@ -39,7 +39,15 @@ void ColnodAPI::downloadData()
void ColnodAPI::processData(const std::shared_ptr<Data> &data) void ColnodAPI::processData(const std::shared_ptr<Data> &data)
{ {
for (const auto &token : data->updatedTokens) {
qInfo(colnod).noquote() << Message::massageTemplate("Updating", "token", "colnod", token->name());
}
for (const auto &id : data->deletedTokens) {
qInfo(colnod).noquote() << Message::massageTemplate("Deleting", "token", "colnod", id);
}
if (!data->updatedTokens.isEmpty() || !data->deletedTokens.isEmpty()) {
qInfo(colnod) << dash;
}
qInfo(colnod) << tab << "-> DATA PROCESSED TO COLNOD:"; qInfo(colnod) << tab << "-> DATA PROCESSED TO COLNOD:";
qInfo(colnod) << tab << tab << data->updatedTokens.size() << "TOKENS UPDATED"; qInfo(colnod) << tab << tab << data->updatedTokens.size() << "TOKENS UPDATED";
qInfo(colnod) << tab << tab << data->deletedTokens.size() << "TOKENS DELETED"; qInfo(colnod) << tab << tab << data->deletedTokens.size() << "TOKENS DELETED";

View File

@ -34,26 +34,35 @@ bool DatabaseAPI::executeQuery(QSqlQuery &query, const QString &statement)
return true; return true;
} }
void DatabaseAPI::downloadData() bool DatabaseAPI::downloadData()
{ {
bool res = true;
auto updatedQuery = mDbMan->createQuery(); auto updatedQuery = mDbMan->createQuery();
auto deletedQuery = mDbMan->createQuery(); auto deletedQuery = mDbMan->createQuery();
if (!executeQuery(updatedQuery, "SELECT * FROM colnod_token WHERE last_modified > last_update AND deleted = false")) { if (!executeQuery(updatedQuery, "SELECT * FROM colnod_token WHERE last_modified > last_update AND deleted = false")) {
qWarning(database) << "ERROR during geting new/updated tokens from db."; qWarning(database) << "ERROR during geting new/updated tokens from db.";
res = false;
} }
if (!executeQuery(deletedQuery, "SELECT id FROM colnod_token WHERE last_modified > last_update AND deleted = true")) { if (!executeQuery(deletedQuery, "SELECT id FROM colnod_token WHERE last_modified > last_update AND deleted = true")) {
qWarning(database) << "ERROR during geting marked tokens for deletion from db."; qWarning(database) << "ERROR during geting marked tokens for deletion from db.";
res = false;
} }
emit downloadDataFinished(composeData(updatedQuery, deletedQuery)); emit downloadDataFinished(composeData(updatedQuery, deletedQuery));
return res;
} }
void DatabaseAPI::processData(const std::shared_ptr<Data> &data) bool DatabaseAPI::processData(const std::shared_ptr<Data> &data)
{ {
uploadTokens(data->updatedTokens); uploadTokens(data->updatedTokens);
uploadSubjects(data->updatedSubjects); uploadSubjects(data->updatedSubjects);
deleteItems(data->deletedTokens, "colnod_token"); deleteItems(data->deletedTokens, "colnod_token");
deleteItems(data->deletedSubjects, "colnod_subject"); deleteItems(data->deletedSubjects, "colnod_subject");
if ( !data->updatedTokens.isEmpty() ||
!data->updatedSubjects.isEmpty() ||
!data->deletedTokens.isEmpty() ||
!data->deletedSubjects.isEmpty()) {
qInfo(database) << dash;
}
qInfo(database) << tab << "-> DATA PROCESSED TO DATABASE:"; qInfo(database) << tab << "-> DATA PROCESSED TO DATABASE:";
qInfo(database) << tab << tab << data->updatedTokens.size() << "TOKENS ADDED/UPDATED"; qInfo(database) << tab << tab << data->updatedTokens.size() << "TOKENS ADDED/UPDATED";
qInfo(database) << tab << tab << data->deletedTokens.size() << "TOKENS DELETED"; qInfo(database) << tab << tab << data->deletedTokens.size() << "TOKENS DELETED";
@ -147,6 +156,8 @@ qint64 DatabaseAPI::getNow()
emit error(); emit error();
} }
query.next(); query.next();
qDebug() << "Database time:" << QDateTime::fromMSecsSinceEpoch(query.value(0).toLongLong()).toString("yyyy-MM-dd hh:mm:ss.zzz");
qDebug() << "Current time:" << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
return query.value(0).toLongLong(); return query.value(0).toLongLong();
} }
@ -170,7 +181,7 @@ void DatabaseAPI::initNewTokens()
uploadTokens(tokensToInit); uploadTokens(tokensToInit);
} }
void DatabaseAPI::uploadTokens(const QHash<QString, std::shared_ptr<Token>> &tokens) bool DatabaseAPI::uploadTokens(const QHash<QString, std::shared_ptr<Token>> &tokens)
{ {
auto query = mDbMan->createQuery(); auto query = mDbMan->createQuery();
for (const auto &token : tokens) { for (const auto &token : tokens) {
@ -185,11 +196,13 @@ void DatabaseAPI::uploadTokens(const QHash<QString, std::shared_ptr<Token>> &tok
if (!query.isActive()) { if (!query.isActive()) {
mValid = false; mValid = false;
qWarning(database) << "ERROR durning inserting/updating of token:" << token->name(); qWarning(database) << "ERROR durning inserting/updating of token:" << token->name();
return false;
} }
} }
return true;
} }
void DatabaseAPI::uploadSubjects(const QHash<QString, std::shared_ptr<Subject>> &subjects) bool DatabaseAPI::uploadSubjects(const QHash<QString, std::shared_ptr<Subject>> &subjects)
{ {
auto query = mDbMan->createQuery(); auto query = mDbMan->createQuery();
for (const auto &subject : subjects) { for (const auto &subject : subjects) {
@ -217,11 +230,13 @@ void DatabaseAPI::uploadSubjects(const QHash<QString, std::shared_ptr<Subject>>
if (!query.isActive()) { if (!query.isActive()) {
mValid = false; mValid = false;
qWarning(database) << "ERROR durning inserting/updating of subject attribute:" << subject->name(); qWarning(database) << "ERROR durning inserting/updating of subject attribute:" << subject->name();
return false;
} }
} }
return true;
} }
void DatabaseAPI::deleteItems(const QList<QString> &ids, const QString &tableName) bool DatabaseAPI::deleteItems(const QList<QString> &ids, const QString &tableName)
{ {
auto query = mDbMan->createQuery(); auto query = mDbMan->createQuery();
QString nowString = QDateTime::fromMSecsSinceEpoch(getLastSync()).toString("yyyy-MM-dd hh:mm:ss.zzz"); QString nowString = QDateTime::fromMSecsSinceEpoch(getLastSync()).toString("yyyy-MM-dd hh:mm:ss.zzz");
@ -233,18 +248,22 @@ void DatabaseAPI::deleteItems(const QList<QString> &ids, const QString &tableNam
query.bindValue(":now", nowString); query.bindValue(":now", nowString);
if (!executeQuery(query)) { if (!executeQuery(query)) {
qWarning(database) << "ERROR during marking token as deleted:" << id; qWarning(database) << "ERROR during marking token as deleted:" << id;
return false;
} }
} }
return true;
} }
std::shared_ptr<Token> DatabaseAPI::getToken(const QString &id) std::shared_ptr<Token> DatabaseAPI::getToken(QString &id)
{ {
auto query = mDbMan->createQuery(); auto query = mDbMan->createQuery();
query.prepare("SELECT * FROM colnod_token WHERE id = :id"); query.prepare("SELECT * FROM colnod_token WHERE d = :id");
query.bindValue(":id", id); query.bindValue(":id", id);
if (!executeQuery(query)) { if (!executeQuery(query)) {
qCritical(database) << "ERROR during accessing existing tokens"; qCritical(database) << "ERROR during accessing existing tokens. EXIT";
emit error(); emit error();
id = QString();
return nullptr;
} }
auto list = utils->tableFromQuery<Token>(query); auto list = utils->tableFromQuery<Token>(query);
if (list.isEmpty()) if (list.isEmpty())
@ -252,10 +271,13 @@ std::shared_ptr<Token> DatabaseAPI::getToken(const QString &id)
return list.at(0); return list.at(0);
} }
bool DatabaseAPI::isAlreadyDeleted(const QString &id) bool DatabaseAPI::isAlreadyDeleted(QString &id)
{ {
auto token = getToken(id); auto token = getToken(id);
if (!token) { if (!token) {
if (id.isEmpty()) {
}
qWarning(database) << "Token deleted in colnod doesn't exists in db, will be noted as already deleted in stats"; qWarning(database) << "Token deleted in colnod doesn't exists in db, will be noted as already deleted in stats";
return true; return true;
} }
@ -270,14 +292,14 @@ bool DatabaseAPI::isValid()
return mValid; return mValid;
} }
bool DatabaseAPI::exists(const QString &id, const QString &tableName) int DatabaseAPI::exists(const QString &id, const QString &tableName)
{ {
auto query = mDbMan->createQuery(); auto query = mDbMan->createQuery();
query.prepare(QString("SELECT 1 FROM %1 WHERE id = :id").arg(tableName)); query.prepare(QString("SELECT 1 FROM %1 WHERE id = :id").arg(tableName));
query.bindValue(":id", id); query.bindValue(":id", id);
if (!executeQuery(query)) { if (!executeQuery(query)) {
qCritical(database) << "ERROR during accessing existing tokens. EXIT(1)"; qCritical(database) << "ERROR during accessing existing tokens. EXIT(1)";
emit error(); return -1;
} }
return query.next(); return query.next();
} }
@ -289,7 +311,7 @@ qint16 DatabaseAPI::getNumOfTokensOfSubject(const QString &id)
query.bindValue(":id", id); query.bindValue(":id", id);
if (!executeQuery(query)) { if (!executeQuery(query)) {
qCritical(database) << "ERROR during accessing existing tokens. EXIT(1)"; qCritical(database) << "ERROR during accessing existing tokens. EXIT(1)";
emit error(); return -1;
} }
return static_cast<qint16>(query.size()); return static_cast<qint16>(query.size());
} }
@ -301,7 +323,7 @@ QString DatabaseAPI::getSubjectNameByTokenId(const QString &tokenId)
query.bindValue(":tokenId", tokenId); query.bindValue(":tokenId", tokenId);
if (!executeQuery(query)) { if (!executeQuery(query)) {
qCritical(database) << "ERROR during accessing existing subject. EXIT(1)"; qCritical(database) << "ERROR during accessing existing subject. EXIT(1)";
emit error(); return "error";
} }
if (query.next()) if (query.next())
return query.value(0).toString(); return query.value(0).toString();

View File

@ -8,6 +8,7 @@
#include "serversdk/databasetable.h" #include "serversdk/databasetable.h"
#include "serversdk/databaseutils.h" #include "serversdk/databaseutils.h"
#include "serversdk/logger.h" #include "serversdk/logger.h"
#include <QCoreApplication>
Q_DECLARE_LOGGING_CATEGORY(database) Q_DECLARE_LOGGING_CATEGORY(database)
@ -21,8 +22,8 @@ public:
bool executeQuery(QSqlQuery &query, const QString &statement = QString()); bool executeQuery(QSqlQuery &query, const QString &statement = QString());
void downloadData(); bool downloadData();
void processData(const std::shared_ptr<Data> &data); bool processData(const std::shared_ptr<Data> &data);
qint64 getLastSync(); qint64 getLastSync();
void setLastSync(qint64 timestamp); void setLastSync(qint64 timestamp);
void setLastUpdate(const QHash<QString, std::shared_ptr<Token> > &tokens); void setLastUpdate(const QHash<QString, std::shared_ptr<Token> > &tokens);
@ -32,18 +33,18 @@ public:
void initNewTokens(); void initNewTokens();
// process data // process data
void uploadTokens(const QHash<QString, std::shared_ptr<Token> > &tokens); bool uploadTokens(const QHash<QString, std::shared_ptr<Token> > &tokens);
void uploadSubjects(const QHash<QString, std::shared_ptr<Subject> > &subjects); bool uploadSubjects(const QHash<QString, std::shared_ptr<Subject> > &subjects);
void deleteItems(const QList<QString> &ids, const QString &tableName); bool deleteItems(const QList<QString> &ids, const QString &tableName);
std::shared_ptr<Token> getToken(const QString &id); std::shared_ptr<Token> getToken(QString &id);
bool isAlreadyDeleted(const QString &id); bool isAlreadyDeleted(QString &id);
bool isValid(); bool isValid();
private: private:
bool exists(const QString &id, const QString &tableName); int exists(const QString &id, const QString &tableName);
QSqlQuery getUpdatedTokens(); QSqlQuery getUpdatedTokens();
std::shared_ptr<Data> composeData(const QSqlQuery &updatedQuery, QSqlQuery &deletedQuery); std::shared_ptr<Data> composeData(const QSqlQuery &updatedQuery, QSqlQuery &deletedQuery);

View File

@ -37,7 +37,7 @@ bool SyncManager::init()
} }
void SyncManager::run() bool SyncManager::run()
{ {
qint64 syncBegin = database->getNow(); qint64 syncBegin = database->getNow();
@ -79,8 +79,9 @@ void SyncManager::run()
}); });
} }
void SyncManager::downloadData() bool SyncManager::downloadData()
{ {
bool res = true;
qInfo(syncmanager) << equals; qInfo(syncmanager) << equals;
qInfo(syncmanager) << "DOWNLOADING DATA -> BEGIN"; qInfo(syncmanager) << "DOWNLOADING DATA -> BEGIN";
qInfo(syncmanager) << dash; qInfo(syncmanager) << dash;
@ -89,12 +90,17 @@ void SyncManager::downloadData()
connect(colnod.get(), &ColnodAPI::downloadDataFinished, this, &SyncManager::saveColnodData); connect(colnod.get(), &ColnodAPI::downloadDataFinished, this, &SyncManager::saveColnodData);
connect(database.get(), &DatabaseAPI::downloadDataFinished, this, &SyncManager::saveDatabaseData); connect(database.get(), &DatabaseAPI::downloadDataFinished, this, &SyncManager::saveDatabaseData);
database->downloadData(); if (!database->downloadData()) {
res = false;
}
colnod->downloadData(); colnod->downloadData();
return true;
} }
// finds conflicts -> changes on both sides (colnod and DB), apply newer change // finds conflicts -> changes on both sides (colnod and DB), apply newer change
void SyncManager::prepareData() bool SyncManager::prepareData()
{ {
qInfo(syncmanager) << equals; qInfo(syncmanager) << equals;
qInfo(syncmanager) << "PREPARING DATA -> BEGIN"; qInfo(syncmanager) << "PREPARING DATA -> BEGIN";
@ -176,9 +182,10 @@ void SyncManager::prepareData()
qInfo(syncmanager) << "PREPARING DATA -> FINISHED"; qInfo(syncmanager) << "PREPARING DATA -> FINISHED";
qInfo(syncmanager) << equals; qInfo(syncmanager) << equals;
return true;
} }
void SyncManager::processData() bool SyncManager::processData()
{ {
qInfo(syncmanager) << equals; qInfo(syncmanager) << equals;
qInfo(syncmanager) << "PROCESSING DATA -> BEGIN"; qInfo(syncmanager) << "PROCESSING DATA -> BEGIN";
@ -189,6 +196,7 @@ void SyncManager::processData()
database->processData(colnodDataToProcess); database->processData(colnodDataToProcess);
connect(colnod.get(), &ColnodAPI::dataProcessFinished, this, &SyncManager::dataProcessFinished); connect(colnod.get(), &ColnodAPI::dataProcessFinished, this, &SyncManager::dataProcessFinished);
colnod->processData(databaseDataToProcess); colnod->processData(databaseDataToProcess);
return true;
} }
void SyncManager::updateLastUpdate(qint64 syncBegin) void SyncManager::updateLastUpdate(qint64 syncBegin)

View File

@ -8,17 +8,16 @@ Q_DECLARE_LOGGING_CATEGORY(syncmanager)
class SyncManager : public QObject class SyncManager : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SyncManager(bool dryMode); explicit SyncManager(bool dryMode, const std::function<void()> &onError = nullptr);
bool init(); bool init();
void run(); bool run();
private: private:
void downloadData(); bool downloadData();
void prepareData(); bool prepareData();
void processData(); bool processData();
void updateLastUpdate(qint64 syncBegin); void updateLastUpdate(qint64 syncBegin);
@ -32,6 +31,8 @@ signals:
void dataProcessFinished(); void dataProcessFinished();
void syncFinished(); void syncFinished();
void error();
private: private:
std::shared_ptr<ColnodAPI> colnod; std::shared_ptr<ColnodAPI> colnod;
std::shared_ptr<DatabaseAPI> database; std::shared_ptr<DatabaseAPI> database;
@ -47,4 +48,6 @@ private:
int dataAmount = 0; int dataAmount = 0;
bool mDryMode; bool mDryMode;
std::function<void()> onError = nullptr;
}; };