add 5 min loop

This commit is contained in:
ondra 2020-12-22 16:05:21 +01:00
parent de021e0834
commit be9064c46e
10 changed files with 279 additions and 95 deletions

View File

@ -8,6 +8,7 @@
#include "../colnod/colnodapi.h" #include "../colnod/colnodapi.h"
#include "../colnod/syncmanager.h" #include "../colnod/syncmanager.h"
#include "../colnod/logutils.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@ -29,7 +30,9 @@ int main(int argc, char *argv[])
// Logger initializiaton // Logger initializiaton
serversdk::initAppLogger(); // serversdk::initAppLogger();
LogUtils::initLogger(false);
// Log messge Filtering // Log messge Filtering
QStringList filters; QStringList filters;
@ -47,11 +50,14 @@ int main(int argc, char *argv[])
return -1; return -1;
} }
syncManager.init();
QCoreApplication::connect(&syncManager, &SyncManager::end, [&]{
QTimer::singleShot(300000, &syncManager, &SyncManager::startSynchronization);
});
// Synchronizaiton // Synchronizaiton
if (!syncManager.startSynchronization()) { syncManager.startSynchronization();
qCritical() << "Not possible to start synchronization";
return -1;
}
return QCoreApplication::exec(); return QCoreApplication::exec();
} }

View File

@ -9,7 +9,8 @@ SOURCES += \
$$PWD/databaseapi.cpp \ $$PWD/databaseapi.cpp \
$$PWD/subject.cpp \ $$PWD/subject.cpp \
$$PWD/syncmanager.cpp \ $$PWD/syncmanager.cpp \
$$PWD/token.cpp $$PWD/token.cpp \
$$PWD/logutils.cpp
HEADERS += \ HEADERS += \
$$PWD/colnodapi.h \ $$PWD/colnodapi.h \
@ -17,6 +18,7 @@ HEADERS += \
$$PWD/databaseapi.h \ $$PWD/databaseapi.h \
$$PWD/subject.h \ $$PWD/subject.h \
$$PWD/syncmanager.h \ $$PWD/syncmanager.h \
$$PWD/token.h $$PWD/token.h \
$$PWD/logutils.h
include(../../server-sdk/serversdk.pri) include(../../server-sdk/serversdk.pri)

View File

@ -155,8 +155,9 @@ bool ColnodAPI::downloadData(const qint64 &time)
return true; return true;
} }
void ColnodAPI::processData(const std::shared_ptr<Data> &data) void ColnodAPI::processData(const std::shared_ptr<PreparedData> &prepdata)
{ {
auto data = prepdata->databaseData;
// emit signal when finished // emit signal when finished
auto checkData = [=]() { auto checkData = [=]() {
int dataCount = data->incrementCounter(); int dataCount = data->incrementCounter();
@ -185,7 +186,7 @@ void ColnodAPI::processData(const std::shared_ptr<Data> &data)
!data->updatedSubjects.isEmpty() || !data->deletedSubjects.isEmpty()) { !data->updatedSubjects.isEmpty() || !data->deletedSubjects.isEmpty()) {
qInfo(colnod) << dash; qInfo(colnod) << dash;
} }
emit dataProcessFinished(mValid); emit dataProcessFinished(mValid, prepdata);
} }
}; };

View File

@ -72,7 +72,7 @@ public:
* @brief Push all data prepare during synchronization to Colnod * @brief Push all data prepare during synchronization to Colnod
* @param data Data which are pushing to Colnod * @param data Data which are pushing to Colnod
*/ */
void processData(const std::shared_ptr<Data> &data); void processData(const std::shared_ptr<PreparedData> &prepdata);
/** /**
* @brief Endpoint of Colnod API * @brief Endpoint of Colnod API
@ -124,7 +124,7 @@ signals:
* @brief Signal which transfer data to Sync Manager * @brief Signal which transfer data to Sync Manager
*/ */
void downloadDataFinished(std::shared_ptr<Data> = std::shared_ptr<Data>()); void downloadDataFinished(std::shared_ptr<Data> = std::shared_ptr<Data>());
void dataProcessFinished(bool success = true); void dataProcessFinished(bool success = true, std::shared_ptr<PreparedData> = nullptr);
void authTokenUpdated(bool success); void authTokenUpdated(bool success);
private: private:

View File

@ -326,3 +326,7 @@ QString DatabaseAPI::getSubjectNameByTokenId(const QString &tokenId)
qWarning() << "Token:" << tokenId << "is not assigned to any subject"; qWarning() << "Token:" << tokenId << "is not assigned to any subject";
return "(No subject)"; return "(No subject)";
} }
bool DatabaseAPI::isOpen() {
return mDbMan->isOpen();
}

View File

@ -106,6 +106,7 @@ public:
* @brief Check if this sync was without any problem * @brief Check if this sync was without any problem
*/ */
bool isValid(); bool isValid();
bool isOpen();
// Helper functions for naming new tokens // Helper functions for naming new tokens
qint16 getNumOfTokensOfSubject(const QString &id); qint16 getNumOfTokensOfSubject(const QString &id);

97
src/colnod/logutils.cpp Normal file
View File

@ -0,0 +1,97 @@
#include "logutils.h"
namespace LogUtils{
static bool verbose;
void initLogger(bool vb)
{
verbose = vb;
if (!QDir(logFolderName).exists()) {
QDir().mkdir(logFolderName);
}
deleteOldLogs();
initLogFileName();
QFile outFile(logFileName);
if (outFile.open(QIODevice::WriteOnly | QIODevice::Append))
{
qInstallMessageHandler(myMessageHandler);
} else {
qWarning() << "Cannot open log file.";
}
}
void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QFile outFileCheck(logFileName);
QFileInfo fileInfo(outFileCheck);
if (fileInfo.created().date() < QDateTime::currentDateTime().date()) {
QFile logFile(logFileName);
logFile.close();
deleteOldLogs();
initLogFileName();
}
QByteArray localMsg = msg.toLocal8Bit();
QString fileString(context.file);
fileString = fileString.mid(fileString.lastIndexOf("\\")+1);
auto date = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
QString txt;
switch (type) {
case QtDebugMsg:
if (verbose)
txt = date + " | " + QString("DEBUG").leftJustified(8,' ') + " | " + localMsg;
break;
case QtInfoMsg:
txt = date + " | " + QString("INFO").leftJustified(8,' ') + " | " + localMsg;
break;
case QtWarningMsg:
txt = date + " | " + QString("WARNING").leftJustified(8,' ') + " | " + QString(fileString + ':' + QString::number(context.line)).rightJustified(19, ' ') + " | " + localMsg;
break;
case QtCriticalMsg:
txt = date + " | " + QString("CRITICAL").leftJustified(8,' ') + " | " + QString(fileString + ':' + QString::number(context.line)).rightJustified(19, ' ') + " | " + localMsg;
break;
case QtFatalMsg:
txt = date + " | " + QString("FATAL").leftJustified(8,' ') + " | " + QString(fileString + ':' + QString::number(context.line)).rightJustified(19, ' ') + " | " + localMsg;
abort();
}
if (!txt.isEmpty()) {
QFile outFile(logFileName);
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream textStream(&outFile);
if (!txt.isEmpty()) textStream << txt << endl;
}
}
void deleteOldLogs(int days)
{
auto today = QDateTime::currentDateTime();
QDir dir;
dir.setFilter(QDir::Files);
dir.setSorting(QDir::Time | QDir::Reversed);
dir.setPath(logFolderName);
auto filesInfo = dir.entryInfoList();
int i = 0;
if (!filesInfo.isEmpty()) {
while (filesInfo[i].created().daysTo(today) > days) {
QString path = filesInfo[i++].absoluteFilePath();
QFile file(path);
file.remove();
qDebug() << "File:" << path << "has been deleted!";
}
}
}
void initLogFileName()
{
logFileName = QString(logFolderName + "/log_%1.txt").arg(QDate::currentDate().toString("yyyy_MM_dd"));
}
void setLogFolder(QString path)
{
logFolderName = path;
}
}

25
src/colnod/logutils.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include <QByteArray>
#include <QString>
#include <QDateTime>
#include <QDate>
#include <QDebug>
#include <QDir>
namespace LogUtils
{
void initLogger(bool vb = false);
void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
void deleteOldLogs(int days = 90);
void initLogFileName();
void setLogFolder(QString path);
static QString logFileName;
static QString logFolderName = "/var/spaceti/log/colnod";
//static constexpr int logSize = 1024 * 0;
//static constexpr int logFileCount = 0;
};

View File

@ -20,64 +20,54 @@ bool SyncManager::databaseInitialization()
return false; return false;
} }
// Get last synchronizaiton date
qint64 lastsync_in_ms = database->getLastSync();
if (lastsync_in_ms == -1) {
qCritical(syncmanager) << "Not possible to get last synchronization date";
return false;
}
// here -> nothing can fail
mlastSync.setTimestamp(lastsync_in_ms);
colnod = std::make_shared<ColnodAPI>(&reqMan, mDryMode); colnod = std::make_shared<ColnodAPI>(&reqMan, mDryMode);
return true; return true;
} }
bool SyncManager::startSynchronization()
{
// Need current time from db server
qint64 syncBegin = database->getNow();
if (syncBegin == -1) {
qCritical(syncmanager) << "Not possible to get last sync date";
return false;
}
qInfo(syncmanager) << tab << "- begin sync ( previous sync" << mlastSync.toDateString() << ")"; void SyncManager::init() {
// GETTING DATA FROM DATABASE // qint64 begin = syncBegin;
auto databaseData = database->downloadData();
if (!databaseData) {
qCritical(syncmanager) << "not possible to get data from database";
return false;
}
// NOW I HAVE DATA FROM DATABASE
colnod->downloadData(mlastSync.timestamp());
connect(colnod.get(), &ColnodAPI::downloadDataFinished, [=](const std::shared_ptr<Data> &colnodData) { connect(colnod.get(), &ColnodAPI::downloadDataFinished, [=](const std::shared_ptr<Data> &colnodData) {
// NOW I HAVE DATA FROM COLNOD // NOW I HAVE DATA FROM COLNOD
if (!colnodData) { if (!colnodData) {
qCritical(syncmanager) << "Not possible to get correct data from colnod"; qCritical(syncmanager) << "Not possible to get correct data from colnod";
QCoreApplication::exit(-1); emit end();
return; return;
} }
std::unique_ptr<PreparedData> preparedData = prepareData(databaseData, colnodData); // GETTING DATA FROM DATABASE
auto databaseData = database->downloadData();
if (!databaseData) {
emit end();
return;
}
// NOW I HAVE DATA FROM DATABASE
std::shared_ptr<PreparedData> preparedData = prepareData(databaseData, colnodData);
if (!preparedData) { if (!preparedData) {
qCritical(syncmanager) << "Not possible to compose data"; qCritical(syncmanager) << "Not possible to compose data";
QCoreApplication::exit(-1); emit end();
return; return;
} }
if (!database->processData(preparedData->colnodData)) { if (!database->processData(preparedData->colnodData)) {
qCritical(syncmanager) << "Not possible to upload data to database"; qCritical(syncmanager) << "Not possible to upload data to database";
err = true;
return;
} }
colnod->processData(preparedData);
// data is processed to other sides });
connect(colnod.get(), &ColnodAPI::dataProcessFinished, [&,syncBegin](bool success){
connect(colnod.get(), &ColnodAPI::dataProcessFinished, [=](bool success, std::shared_ptr<PreparedData> preparedData){
if (!success) { if (!success) {
qCritical(syncmanager) << "Not possible to upload data to colnod"; qCritical(syncmanager) << "Not possible to upload data to colnod";
err = true;
} }
// REUPDATE tokens pushed from database to colnod (cause of lastUpdate time) // REUPDATE tokens pushed from database to colnod (cause of lastUpdate time)
@ -85,57 +75,107 @@ bool SyncManager::startSynchronization()
// download data changes in this sync // download data changes in this sync
colnod->updateAuthToken(); colnod->updateAuthToken();
connect(colnod.get(), &ColnodAPI::authTokenUpdated, [&,syncBegin](bool success) { QTimer timer;
timer.setSingleShot(true);
QEventLoop loop;
QMetaObject::Connection myConnect = connect(colnod.get(), &ColnodAPI::authTokenUpdated, [this, &loop](bool success){
if (!success) { if (!success) {
qCritical(syncmanager) << "Cannot login to Colnod."; qCritical(syncmanager) << "Cannot login to Colnod.";
emit end();
}
qDebug() << "test loop";
loop.quit();
});
// connect(colnod.get(), &ColnodAPI::authTokenUpdated, [this](bool success) {\
// if (!success) {
// qCritical(syncmanager) << "Cannot login to Colnod.";
// emit end();
// }
// qDebug() << "test loop";
// return;
// });
// connect( colnod.get(), &ColnodAPI::authTokenUpdated, &loop, &QEventLoop::quit);
connect( &timer, &QTimer::timeout, &loop, &QEventLoop::quit );
timer.start(30000);
loop.exec();
loop.deleteLater();
disconnect(myConnect);
qDebug() << "Loop ended";
if(!timer.isActive()) {
qCritical("Cannot login to Colnod");
emit end();
return; return;
} }
Timestamp time; Timestamp time;
time.setTimestamp(syncBegin - 75 * 1000); time.setTimestamp(syncBegin - 100 * 1000);
auto tokensRequest = colnod->getTokensUpdated(time); auto tokensRequest = colnod->getTokensUpdated(time);
// updated data are ready // updated data are ready
connect(tokensRequest.get(), &serversdk::Request::finished, [=](){
connect(tokensRequest.get(), &serversdk::Request::finished, [=](){
auto uploadedData = std::make_shared<Data>(); auto uploadedData = std::make_shared<Data>();
uploadedData->loadTokensFromJson(tokensRequest->responseData()); uploadedData->loadTokensFromJson(tokensRequest->responseData());
if (!uploadedData) { if (!uploadedData) {
qCritical(syncmanager) << "Not possible to get correct data from colnod"; qCritical(syncmanager) << "Not possible to get correct data from colnod";
QCoreApplication::exit(-1); emit end();
return; return;
} }
if (!database->uploadTokens(uploadedData->updatedTokens, {"lastModified"})) { if (!database->uploadTokens(uploadedData->updatedTokens, {"lastModified"})) {
qCritical(syncmanager) << "Not possible to upload data to database"; qCritical(syncmanager) << "Not possible to upload data to database";
QCoreApplication::exit(-1); emit end();
return; return;
} }
database->reupdateDeleted(databaseData->deletedTokens); database->reupdateDeleted(preparedData->databaseData->deletedTokens);
if (!database->isValid() || !colnod->isValid()) { if (!database->isValid() || !colnod->isValid() || err || !database->setLastSync(syncBegin)) {
qWarning(syncmanager) << "Unsuccessful FINISH, check warnings"; qWarning(syncmanager) << "Unsuccessful FINISH, check warnings";
} } else {
else {
// set new time of last sync to this time of this run
if (!database->setLastSync(syncBegin)) {
qWarning(syncmanager) << "Unsuccessful FINISH, check warnings";
}
qInfo(syncmanager) << "Successful FINISH"; qInfo(syncmanager) << "Successful FINISH";
} }
QCoreApplication::exit(); emit end();
});
}); });
});
}
bool SyncManager::startSynchronization()
{
if (!database->isOpen() ) {
if (!database->open()) {
qCritical(syncmanager) << "Cannot open database.";
return false;
}
}
qint64 lastsync_in_ms = database->getLastSync();
if (lastsync_in_ms == -1) {
qCritical(syncmanager) << "Not possible to get last synchronization date";
return false;
}
mlastSync.setTimestamp(lastsync_in_ms);
// Need current time from db server
err = false;
syncBegin = database->getNow();
if (syncBegin == -1) {
qCritical(syncmanager) << "Not possible to get last sync date";
emit end();
return false;
}
qint64 offset = 75 * 1000;
qInfo(syncmanager) << tab << "Begin sync ( previous sync" << mlastSync.toDateString() << ")";
colnod->downloadData(mlastSync.timestamp() - offset);
});
colnod->processData(preparedData->databaseData);
});
return true; return true;
} }
// goes through downloaded data and check if consist conflicts (both sides edit), already sync/deleted tokens or new tokens // goes through downloaded data and check if consist conflicts (both sides edit), already sync/deleted tokens or new tokens
std::unique_ptr<PreparedData> SyncManager::prepareData(const std::shared_ptr<Data> &databaseData, const std::shared_ptr<Data> &colnodData) std::shared_ptr<PreparedData> SyncManager::prepareData(const std::shared_ptr<Data> &databaseData, const std::shared_ptr<Data> &colnodData)
{ {
auto preparedColnodData = std::make_shared<Data>(); auto preparedColnodData = std::make_shared<Data>();
auto preparedDatabaseData = std::make_shared<Data>(); auto preparedDatabaseData = std::make_shared<Data>();

View File

@ -13,6 +13,7 @@ public:
explicit SyncManager(bool dryMode); explicit SyncManager(bool dryMode);
bool databaseInitialization(); bool databaseInitialization();
void init();
bool startSynchronization(); bool startSynchronization();
private: private:
@ -22,7 +23,12 @@ private:
* @param data from colnod * @param data from colnod
* @return prepared data to be pushed into colnod and db * @return prepared data to be pushed into colnod and db
*/ */
std::unique_ptr<PreparedData> prepareData(const std::shared_ptr<Data> &databaseData, const std::shared_ptr<Data> &colnodData); std::shared_ptr<PreparedData> prepareData(const std::shared_ptr<Data> &databaseData, const std::shared_ptr<Data> &colnodData);
signals:
void error();
void end();
private: private:
/** /**
@ -37,6 +43,8 @@ private:
serversdk::RequestManager reqMan; serversdk::RequestManager reqMan;
serversdk::DatabaseManager dbMan; serversdk::DatabaseManager dbMan;
Timestamp mlastSync; Timestamp mlastSync;
qint64 syncBegin;
bool err;
bool mDryMode; bool mDryMode;
}; };