This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
powersync-core/tests/auto/loggingdirect/testloggingdirect.cpp
Michael Zanetti 3eac06de6e Threaded log database
This
a) makes the log db threaded by using QtConcurrent to run queries in a
different thread but still keeps ordering of the queries and always
only allows a single query at a time (QSql is not threadsafe). This fixes
removeDevice calls failing if we take more than $jsonprc_timeout to clean
a deleted device from the DB and keeps nymead responsive during that too.

b) generally improces performance of the system by not requiring operations
(emitting events, changing states) to wait for the sync log db entry to be
made.

c) drops some of the houskeeping code on nymea startup. While this will still
do log db housekeeping if the DB exceeds maxDbSize, it will not run
housekeeping on the DB any more at application startup. Reasoning for this
is that there have been reports of rules/log entries beimg destroyed if a
plugin can't be found at application startup. Given our general direction
of working towards more dynamic plugin loading, this might happen more often
in the future and we sure don't want to destroy rules etc when we just
temporarily miss a plugin.

d) tries to fix issue #226 by rotating the DB not only when it fails to open
initially, but also when it fails to insert new entries.
2019-11-15 18:33:10 +01:00

125 lines
4.7 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2017 Michael Zanetti <michael.zanetti@guh.io> *
* *
* This file is part of nymea. *
* *
* nymea is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
**
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with nymea. If not, see <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <QtTest>
#include "logging/logengine.h"
using namespace nymeaserver;
class TestLoggingDirect: public QObject
{
Q_OBJECT
public:
TestLoggingDirect(QObject* parent = nullptr);
private slots:
void benchmarkDB_data();
void benchmarkDB();
private:
LogEngine *engine;
};
TestLoggingDirect::TestLoggingDirect(QObject *parent): QObject(parent)
{
engine = new LogEngine("QSQLITE", "/tmp/nymea-test/nymea.sqlite");
// Setting timeout to 20 mins
qputenv("QTEST_FUNCTION_TIMEOUT", "1200000");
QCoreApplication::instance()->setOrganizationName("nymea-test");
}
void TestLoggingDirect::benchmarkDB_data() {
QTest::addColumn<int>("prefill");
QTest::addColumn<int>("maxSize");
QTest::newRow("empty, no trim") << 0 << 20000;
QTest::newRow("empty, trim") << 1 << 1;
QTest::newRow("10000, no trim") << 10000 << 20000;
QTest::newRow("10000, trim") << 10000 << 10000;
// QTest::newRow("20000, no trim") << 20000 << 30000;
// QTest::newRow("20000, trim") << 20000 << 20000;
// QTest::newRow("30000, no trim") << 30000 << 40000;
// QTest::newRow("30000, trim") << 30000 << 30000;
// QTest::newRow("40000, no trim") << 40000 << 50000;
// QTest::newRow("40000, trim") << 40000 << 40000;
// QTest::newRow("50000, no trim") << 50000 << 60000;
// QTest::newRow("50000, trim") << 50000 << 50000;
// QTest::newRow("60000, no trim") << 60000 << 70000;
// QTest::newRow("60000, trim") << 60000 << 60000;
}
void TestLoggingDirect::benchmarkDB()
{
if (qgetenv("WITH_BENCHMARK").isEmpty()) {
QSKIP("Skipping benchmark tests: export WITH_BENCHMARK=1 to enable it.");
}
QFETCH(int, prefill);
QFETCH(int, maxSize);
// setting max log entries to "prefill" to trim it down to what this test needs.
int overflow = 10;
qDebug() << "Flushing DB for test";
engine->setMaxLogEntries(prefill, overflow);
engine->setMaxLogEntries(maxSize, overflow);
LogEngineFetchJob *job = engine->logEntries();
QSignalSpy fetchSpy(job, &LogEngineFetchJob::finished);
fetchSpy.wait();
QList<LogEntry> entries = job->results();
qDebug() << "DB has" << entries.count() << "entries";
qDebug() << "Prefilling DB for test";
for (int i = entries.count(); i < prefill; i++) {
engine->logSystemEvent(QDateTime::currentDateTime(), true);
}
job = engine->logEntries();
QSignalSpy fetchSpy2(job, &LogEngineFetchJob::finished);
fetchSpy2.wait();
entries = job->results();
qDebug() << "DB has" << entries.count() << "entries";
qDebug() << "Starting benchmark with" << entries.count() << "entries in the db";
QBENCHMARK {
engine->logSystemEvent(QDateTime::currentDateTime(), true);
}
QDateTime now = QDateTime::currentDateTime();
job = engine->logEntries();
QSignalSpy fetchSpy3(job, &LogEngineFetchJob::finished);
fetchSpy3.wait();
entries = job->results();
while (entries.count() > maxSize + overflow) {
qApp->processEvents();
if (now.addSecs(5) < QDateTime::currentDateTime()) {
QVERIFY2(false, QString("Housekeeping didn't work. Have %1 entries but expected to have max %2").arg(entries.count()).arg(QString::number(maxSize)).toLocal8Bit());
}
}
qDebug() << "Ended benchmark with" << entries.count() << "entries in the db";
}
#include "testloggingdirect.moc"
QTEST_MAIN(TestLoggingDirect)