Error handling

This commit is contained in:
Ondřej Fischer 2019-11-26 10:54:43 +01:00
parent a3c9a783e7
commit fc54831952
6 changed files with 176 additions and 26 deletions

@ -1 +1 @@
Subproject commit eddfc401b0282d53ba7289bb5c3ffa41e0287dda Subproject commit 9623578997c33de0700131a40592a83e6cef3289

View File

@ -18,10 +18,10 @@ void ColnodAPI::downloadData()
{ {
// Have to get Login // Have to get Login
auto login = requestLogin(); auto login = requestLogin();
connect(login.get(), &serversdk::Request::finished, this, [=](){ // TODO: error handling connect(login.get(), &serversdk::Request::finished, this, [=](){
// Get token // Get login token
if (login->status() != 0) { if (login->status() != 200) {
qCritical(colnod) << "Login unsuccessful, Status:" << login->status() << "Error message:" ; emit error();
} }
AuthToken token; AuthToken token;
@ -86,6 +86,14 @@ void ColnodAPI::getTokensUpdated(const Timestamp &time)
request->setUserName(authToken); request->setUserName(authToken);
mReqMan->processRequest(request); mReqMan->processRequest(request);
connect(request.get(), &serversdk::Request::finished, [=](){ connect(request.get(), &serversdk::Request::finished, [=](){
if (!checkRequest(request)) {
qWarning(colnod) << "ERROR during calling /TokenManager/getTokensUpdated, request unsuccessful";
mValid = false;
}
else if (!checkResponse(request->responseData())) {
qWarning(colnod) << "Data from /TokenManager/getTokensUpdated are invalid";
mValid = false;
}
saveUpdatedTokens(request->responseData()); saveUpdatedTokens(request->responseData());
emit partOfDataReady(mData); emit partOfDataReady(mData);
}); });
@ -97,6 +105,14 @@ void ColnodAPI::getTokensDeleted(const Timestamp &time)
request->setUserName(authToken); request->setUserName(authToken);
mReqMan->processRequest(request); mReqMan->processRequest(request);
connect(request.get(), &serversdk::Request::finished, [=](){ connect(request.get(), &serversdk::Request::finished, [=](){
if (!checkRequest(request)) {
qWarning(colnod) << "ERROR during calling /TokenManager/getTokensDeleted, request unsuccessful";
mValid = false;
}
else if (!checkResponse(request->responseData())) {
qWarning(colnod) << "Data from /TokenManager/getTokensDeleted are invalid";
mValid = false;
}
saveDeletedTokens(request->responseData()); saveDeletedTokens(request->responseData());
emit partOfDataReady(); emit partOfDataReady();
}); });
@ -108,6 +124,14 @@ void ColnodAPI::getSubjectsUpdated(const Timestamp &time)
request->setUserName(authToken); request->setUserName(authToken);
mReqMan->processRequest(request); mReqMan->processRequest(request);
connect(request.get(), &serversdk::Request::finished, [=](){ connect(request.get(), &serversdk::Request::finished, [=](){
if (!checkRequest(request)) {
qWarning(colnod) << "ERROR during calling /SubjectManager/getSubjectsUpdated, request unsuccessful";
mValid = false;
}
else if (!checkResponse(request->responseData())) {
qWarning(colnod) << "Data from /SubjectManager/getSubjectsUpdated are invalid";
mValid = false;
}
saveUpdatedSubjects(request->responseData()); saveUpdatedSubjects(request->responseData());
emit partOfDataReady(); emit partOfDataReady();
}); });
@ -119,6 +143,14 @@ void ColnodAPI::getSubjectsDeleted(const Timestamp &time)
request->setUserName(authToken); request->setUserName(authToken);
mReqMan->processRequest(request); mReqMan->processRequest(request);
connect(request.get(), &serversdk::Request::finished, [=](){ connect(request.get(), &serversdk::Request::finished, [=](){
if (!checkRequest(request)) {
qWarning(colnod) << "ERROR during calling /SubjectManager/getSubjectsDeleted, request unsuccessful";
mValid = false;
}
else if (!checkResponse(request->responseData())) {
qWarning(colnod) << "Data from /SubjectManager/getSubjectsDeleted are invalid";
mValid = false;
}
saveDeletedSubjects(request->responseData()); saveDeletedSubjects(request->responseData());
emit partOfDataReady(); emit partOfDataReady();
}); });
@ -130,12 +162,17 @@ void ColnodAPI::setTokens(const QHash<QString, std::shared_ptr<Token>> &tokens)
request->setUserName(authToken); request->setUserName(authToken);
mReqMan->processRequest(request); mReqMan->processRequest(request);
connect(request.get(), &serversdk::Request::finished, [=](){ connect(request.get(), &serversdk::Request::finished, [=](){
if (!checkRequest(request)) {
qCritical(colnod) << "ERROR during calling /TokenManager/setTokens, request unsuccessful. EXIT";
emit error();
}
if (checkResponse(request->responseData())) { if (checkResponse(request->responseData())) {
emit partOfDataProcessFinished(); emit partOfDataProcessFinished();
} }
else { else {
qWarning(colnod) << "Tokens wasn't updated"; qWarning(colnod) << "Tokens wasn't updated";
// TODO: error: data wasnt upload to colnod mValid = false;
emit partOfDataProcessFinished();
} }
}); });
} }
@ -146,12 +183,17 @@ void ColnodAPI::deleteTokens(const QList<QString> &ids)
request->setUserName(authToken); request->setUserName(authToken);
mReqMan->processRequest(request); mReqMan->processRequest(request);
connect(request.get(), &serversdk::Request::finished, [=](){ connect(request.get(), &serversdk::Request::finished, [=](){
if (!checkRequest(request)) {
qCritical(colnod) << "ERROR during calling /TokenManager/deleteTokens, request unsuccessful. EXIT";
emit error();
}
if (checkResponse(request->responseData())) { if (checkResponse(request->responseData())) {
emit partOfDataProcessFinished(); emit partOfDataProcessFinished();
} }
else { else {
qWarning(colnod) << "Tokens wasn't deleted"; qWarning(colnod) << "Tokens wasn't deleted";
// TODO: error: data wasnt upload to colnod mValid = false;
emit partOfDataProcessFinished();
} }
}); });
@ -163,6 +205,19 @@ std::shared_ptr<serversdk::Request> ColnodAPI::composeRequest(const QString &end
return std::make_shared<serversdk::Request>("POST", url, data); return std::make_shared<serversdk::Request>("POST", url, data);
} }
bool ColnodAPI::checkRequest(const std::shared_ptr<serversdk::Request> &request)
{
if (request->status() == 200) {
return true;
}
return false;
}
bool ColnodAPI::isValid()
{
return mValid;
}
QString ColnodAPI::password() const QString ColnodAPI::password() const
{ {
return mPassword; return mPassword;

View File

@ -77,12 +77,18 @@ private:
QByteArray getTimestampJson(const qint64 &time); QByteArray getTimestampJson(const qint64 &time);
std::shared_ptr<serversdk::Request> composeRequest(const QString &endpoint, const QByteArray &data); std::shared_ptr<serversdk::Request> composeRequest(const QString &endpoint, const QByteArray &data);
bool checkRequest(const std::shared_ptr<serversdk::Request> &request);
bool isValid();
signals: signals:
void downloadDataFinished(std::shared_ptr<Data> = std::shared_ptr<Data>()); void downloadDataFinished(std::shared_ptr<Data> = std::shared_ptr<Data>());
void partOfDataReady(std::shared_ptr<Data> = std::shared_ptr<Data>()); void partOfDataReady(std::shared_ptr<Data> = std::shared_ptr<Data>());
void partOfDataProcessFinished(); void partOfDataProcessFinished();
void dataProcessFinished(); void dataProcessFinished();
void error();
private: private:
serversdk::RequestManager* mReqMan = nullptr; serversdk::RequestManager* mReqMan = nullptr;
QString mHost = "https://192.168.1.3:8443"; QString mHost = "https://192.168.1.3:8443";
@ -90,6 +96,7 @@ private:
QString mPassword; QString mPassword;
Timestamp mLastSync; Timestamp mLastSync;
bool mDryMode = false; bool mDryMode = false;
bool mValid = false;
std::shared_ptr<Data> mData; std::shared_ptr<Data> mData;

View File

@ -19,12 +19,31 @@ bool DatabaseAPI::open()
QStringLiteral("postgres-connection")); QStringLiteral("postgres-connection"));
} }
bool DatabaseAPI::executeQuery(QSqlQuery &query, const QString &statement)
{
if (statement.isEmpty()) {
query = mDbMan->executeQuery(query);
}
else {
query = mDbMan->executeQuery(query, statement);
}
if (!query.isActive()) {
this->mValid = false;
return false;
}
return true;
}
void DatabaseAPI::downloadData() void DatabaseAPI::downloadData()
{ {
auto updatedQuery = mDbMan->execPlainSql("SELECT * " auto updatedQuery = mDbMan->createQuery();
"FROM colnod_token WHERE last_modified > last_update AND deleted = false"); auto deletedQuery = mDbMan->createQuery();
auto deletedQuery = mDbMan->execPlainSql("SELECT id " if (!executeQuery(updatedQuery, "SELECT * FROM colnod_token WHERE last_modified > last_update AND deleted = false")) {
"FROM colnod_token WHERE last_modified > last_update AND deleted = true"); qWarning(database) << "ERROR during geting new/updated tokens from db.";
}
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.";
}
emit downloadDataFinished(composeData(updatedQuery, deletedQuery)); emit downloadDataFinished(composeData(updatedQuery, deletedQuery));
} }
@ -65,7 +84,11 @@ std::shared_ptr<Data> DatabaseAPI::composeData(const QSqlQuery &updatedQuery, QS
qint64 DatabaseAPI::getLastSync() qint64 DatabaseAPI::getLastSync()
{ {
auto query = mDbMan->execPlainSql("SELECT last_sync FROM config"); auto query = mDbMan->createQuery();
if (!executeQuery(query, "SELECT last_sync FROM config")) {
qCritical(database) << "ERROR during getting time of last sync. Exit.";
emit error();
}
if (query.next()){ if (query.next()){
return query.value(0).toLongLong(); return query.value(0).toLongLong();
} }
@ -77,7 +100,10 @@ void DatabaseAPI::setLastSync(qint64 timestamp)
auto query = mDbMan->createQuery(); auto query = mDbMan->createQuery();
query.prepare("UPDATE config SET last_sync = :last_sync"); query.prepare("UPDATE config SET last_sync = :last_sync");
query.bindValue(":last_sync", timestamp); query.bindValue(":last_sync", timestamp);
mDbMan->executeQuery(query); if (!executeQuery(query)) {
qCritical(database) << "ERROR during set time of this synchronization as last sync time";
emit error();
}
} }
void DatabaseAPI::setLastUpdate(const QHash<QString, std::shared_ptr<Token>> &tokens) void DatabaseAPI::setLastUpdate(const QHash<QString, std::shared_ptr<Token>> &tokens)
@ -87,7 +113,9 @@ void DatabaseAPI::setLastUpdate(const QHash<QString, std::shared_ptr<Token>> &to
query.prepare("UPDATE colnod_token SET last_update = :last_update WHERE id = :id"); query.prepare("UPDATE colnod_token SET last_update = :last_update WHERE id = :id");
query.bindValue(":last_update", token->lastUpdate()); query.bindValue(":last_update", token->lastUpdate());
query.bindValue(":id", token->id()); query.bindValue(":id", token->id());
mDbMan->executeQuery(query); if (!executeQuery(query)) {
qWarning(database) << "ERROR during updating last update of token:" << token->name() << ", it will be synced from Colnod to db in next sync. Last modified will be invalid";
}
} }
qInfo(database) << equals; qInfo(database) << equals;
@ -102,21 +130,32 @@ void DatabaseAPI::setLastUpdate(const QList<QString> ids)
query.prepare("UPDATE colnod_token SET last_update = :last_update WHERE id = :id"); query.prepare("UPDATE colnod_token SET last_update = :last_update WHERE id = :id");
query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(getNow()).toString("yyyy-MM-dd hh:mm:ss.zzz")); query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(getNow()).toString("yyyy-MM-dd hh:mm:ss.zzz"));
query.bindValue(":id", id); query.bindValue(":id", id);
mDbMan->executeQuery(query); if (!executeQuery(query)) {
if (!executeQuery(query)) {
qWarning(database) << "ERROR during updating last update of deleted token:" << id << ", it will be synced from Colnod to db in next sync. Last modified will be invalid";
}
}
} }
} }
qint64 DatabaseAPI::getNow() qint64 DatabaseAPI::getNow()
{ {
auto query = mDbMan->execPlainSql("SELECT EXTRACT(EPOCH FROM NOW())*1000"); auto query = mDbMan->createQuery();
if (!executeQuery(query, "SELECT EXTRACT(EPOCH FROM NOW())*1000")) {
qCritical(database) << "ERROR during getting acctual time from db";
emit error();
}
query.next(); query.next();
return query.value(0).toLongLong(); return query.value(0).toLongLong();
} }
void DatabaseAPI::initNewTokens() void DatabaseAPI::initNewTokens()
{ {
auto query = mDbMan->execPlainSql("SELECT * FROM colnod_token WHERE name IS NULL"); auto query = mDbMan->createQuery();
if (!executeQuery(query, "SELECT * FROM colnod_token WHERE name IS NULL")) {
qWarning(database) << "ERROR during getting uninitialized tokens";
}
QHash<QString, std::shared_ptr<Token>> tokensToInit; QHash<QString, std::shared_ptr<Token>> tokensToInit;
auto list = utils->tableFromQuery<Token>(query); auto list = utils->tableFromQuery<Token>(query);
for (const auto &token : list) { for (const auto &token : list) {
@ -143,6 +182,10 @@ void DatabaseAPI::uploadTokens(const QHash<QString, std::shared_ptr<Token>> &tok
query = utils->insertIntoTable(token.get(), "colnod_token"); query = utils->insertIntoTable(token.get(), "colnod_token");
qInfo(database).noquote() << Message::massageTemplate("Adding", "token", "database", token->name()); qInfo(database).noquote() << Message::massageTemplate("Adding", "token", "database", token->name());
} }
if (!query.isActive()) {
mValid = false;
qWarning(database) << "ERROR durning inserting/updating of token:" << token->name();
}
} }
} }
@ -154,14 +197,15 @@ void DatabaseAPI::uploadSubjects(const QHash<QString, std::shared_ptr<Subject>>
if (exists(attribute->id(), "colnod_subject_attribute")) { if (exists(attribute->id(), "colnod_subject_attribute")) {
query = utils->updateTable(attribute.get(), "colnod_subject_attribute"); query = utils->updateTable(attribute.get(), "colnod_subject_attribute");
} }
else { else {
query = utils->insertIntoTable(attribute.get(), "colnod_subject_attribute"); query = utils->insertIntoTable(attribute.get(), "colnod_subject_attribute");
}
if (!query.isActive()) {
mValid = false;
qWarning(database) << "ERROR durning inserting/updating of subject attribute:" << attribute->attributeValue();
} }
} }
// NOTE: about actions
if (exists(subject->id(), "colnod_subject")) { if (exists(subject->id(), "colnod_subject")) {
query = utils->updateTable(subject.get(), "colnod_subject"); query = utils->updateTable(subject.get(), "colnod_subject");
qInfo(database).noquote() << Message::massageTemplate("Updating", "subject", "database", subject->name()); qInfo(database).noquote() << Message::massageTemplate("Updating", "subject", "database", subject->name());
@ -170,6 +214,10 @@ void DatabaseAPI::uploadSubjects(const QHash<QString, std::shared_ptr<Subject>>
query = utils->insertIntoTable(subject.get(), "colnod_subject"); query = utils->insertIntoTable(subject.get(), "colnod_subject");
qInfo(database).noquote() << Message::massageTemplate("Adding", "subject", "database", subject->name()); qInfo(database).noquote() << Message::massageTemplate("Adding", "subject", "database", subject->name());
} }
if (!query.isActive()) {
mValid = false;
qWarning(database) << "ERROR durning inserting/updating of subject attribute:" << subject->name();
}
} }
} }
@ -183,7 +231,9 @@ void DatabaseAPI::deleteItems(const QList<QString> &ids, const QString &tableNam
query.prepare(QString("UPDATE %1 SET deleted = true, last_update = :now, last_modified = :now WHERE id = :id").arg(tableName)); query.prepare(QString("UPDATE %1 SET deleted = true, last_update = :now, last_modified = :now WHERE id = :id").arg(tableName));
query.bindValue(":id", id); query.bindValue(":id", id);
query.bindValue(":now", nowString); query.bindValue(":now", nowString);
mDbMan->executeQuery(query); if (!executeQuery(query)) {
qWarning(database) << "ERROR during marking token as deleted:" << id;
}
} }
} }
@ -192,7 +242,10 @@ std::shared_ptr<Token> DatabaseAPI::getToken(const 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 id = :id");
query.bindValue(":id", id); query.bindValue(":id", id);
mDbMan->executeQuery(query); if (!executeQuery(query)) {
qCritical(database) << "ERROR during accessing existing tokens";
emit error();
}
auto list = utils->tableFromQuery<Token>(query); auto list = utils->tableFromQuery<Token>(query);
if (list.isEmpty()) if (list.isEmpty())
return nullptr; return nullptr;
@ -208,12 +261,20 @@ bool DatabaseAPI::isAlreadyDeleted(const QString &id)
} }
bool DatabaseAPI::isValid()
{
return mValid;
}
bool DatabaseAPI::exists(const QString &id, const QString &tableName) bool 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);
query = mDbMan->executeQuery(query); if (!executeQuery(query)) {
qCritical(database) << "ERROR during accessing existing tokens. EXIT(1)";
emit error();
}
return query.next(); return query.next();
} }
@ -222,7 +283,11 @@ qint16 DatabaseAPI::getNumOfTokensOfSubject(const QString &id)
auto query = mDbMan->createQuery(); auto query = mDbMan->createQuery();
query.prepare("SELECT 1 FROM colnod_token WHERE subject_id = :id AND deleted = false"); query.prepare("SELECT 1 FROM colnod_token WHERE subject_id = :id AND deleted = false");
query.bindValue(":id", id); query.bindValue(":id", id);
return static_cast<qint16>(mDbMan->executeQuery(query).size()); if (!executeQuery(query)) {
qCritical(database) << "ERROR during accessing existing tokens. EXIT(1)";
emit error();
}
return static_cast<qint16>(query.size());
} }
QString DatabaseAPI::getSubjectNameByTokenId(const QString &tokenId) QString DatabaseAPI::getSubjectNameByTokenId(const QString &tokenId)
@ -230,7 +295,11 @@ QString DatabaseAPI::getSubjectNameByTokenId(const QString &tokenId)
auto query = mDbMan->createQuery(); auto query = mDbMan->createQuery();
query.prepare("SELECT name FROM colnod_subject WHERE id = (SELECT subject_id FROM colnod_token WHERE id = :tokenId)"); query.prepare("SELECT name FROM colnod_subject WHERE id = (SELECT subject_id FROM colnod_token WHERE id = :tokenId)");
query.bindValue(":tokenId", tokenId); query.bindValue(":tokenId", tokenId);
if (mDbMan->executeQuery(query).next()) if (!executeQuery(query)) {
qCritical(database) << "ERROR during accessing existing subject. EXIT(1)";
emit error();
}
if (query.next())
return query.value(0).toString(); return query.value(0).toString();
qWarning() << "Token:" << tokenId << "is not assigned to any subject"; qWarning() << "Token:" << tokenId << "is not assigned to any subject";
return "(No subject)"; return "(No subject)";

View File

@ -19,6 +19,8 @@ public:
bool open(); bool open();
bool executeQuery(QSqlQuery &query, const QString &statement = QString());
void downloadData(); void downloadData();
void processData(const std::shared_ptr<Data> &data); void processData(const std::shared_ptr<Data> &data);
qint64 getLastSync(); qint64 getLastSync();
@ -38,6 +40,8 @@ public:
bool isAlreadyDeleted(const QString &id); bool isAlreadyDeleted(const QString &id);
bool isValid();
private: private:
bool exists(const QString &id, const QString &tableName); bool exists(const QString &id, const QString &tableName);
@ -52,6 +56,7 @@ signals:
private: private:
bool mDryMode; bool mDryMode;
bool mValid = true;
serversdk::DatabaseManager *mDbMan = nullptr; serversdk::DatabaseManager *mDbMan = nullptr;
std::unique_ptr<serversdk::DatabaseUtils> utils; std::unique_ptr<serversdk::DatabaseUtils> utils;
}; };

View File

@ -13,6 +13,12 @@ SyncManager::SyncManager(bool dryMode)
bool SyncManager::init() bool SyncManager::init()
{ {
database = std::make_shared<DatabaseAPI>(&dbMan, mDryMode); database = std::make_shared<DatabaseAPI>(&dbMan, mDryMode);
connect(database.get(), &DatabaseAPI::error, [=](){
QCoreApplication::exit(1);
});
connect(colnod.get(), &ColnodAPI::error, [=](){
QCoreApplication::exit(1);
});
if (database->open()){ if (database->open()){
mlastSync.set_timestamp(database->getLastSync()); mlastSync.set_timestamp(database->getLastSync());
@ -23,7 +29,10 @@ bool SyncManager::init()
if (mlastSync.timestamp() >= 0){ if (mlastSync.timestamp() >= 0){
return true; return true;
} }
qCritical(syncmanager) << "Couldn't get time of last synchronization";
} }
else
qCritical(syncmanager) << "Opening database wasn't successful";
return false; return false;
} }
@ -48,7 +57,12 @@ void SyncManager::run()
updateLastUpdate(syncBegin); updateLastUpdate(syncBegin);
connect(this, &SyncManager::syncFinished, [=](){ connect(this, &SyncManager::syncFinished, [=](){
database->setLastSync(syncBegin); if (database->isValid() && colnod.isValid()) {
database->setLastSync(syncBegin);
}
else {
qWarning(syncmanager) << "Synchronization was unsuccessful, next run of sync will be with same last sync time, check warnings";
}
qInfo(syncmanager).noquote() << "Update last synchronization time to time of this sync (" qInfo(syncmanager).noquote() << "Update last synchronization time to time of this sync ("
<< QDateTime::fromMSecsSinceEpoch(syncBegin).toString("yyyy-MM-dd hh:mm:ss.zzz") << QDateTime::fromMSecsSinceEpoch(syncBegin).toString("yyyy-MM-dd hh:mm:ss.zzz")