From 22dd5f1e8988b03a691487cdad164a82a36e7f8c Mon Sep 17 00:00:00 2001 From: Alexey Andreyev Date: Sat, 2 Feb 2019 23:51:20 +0300 Subject: Connection: separated sync loop logic with delay control Signed-off-by: Alexey Andreyev --- lib/connection.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++++++------- lib/connection.h | 30 +++++++++++++++++++++++- 2 files changed, 90 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/connection.cpp b/lib/connection.cpp index 982145f7..e7f9e4b2 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -45,6 +45,7 @@ #include #include #include +#include using namespace QMatrixClient; @@ -133,8 +134,6 @@ Connection::Connection(const QUrl& server, QObject* parent) , d(std::make_unique(std::make_unique(server))) { d->q = this; // All d initialization should occur before this line - // sync loop: - connect(this, &Connection::syncDone, this, &Connection::getNewEvents); } Connection::Connection(QObject* parent) @@ -232,6 +231,11 @@ void Connection::doConnectToServer(const QString& user, const QString& password, }); } +void Connection::syncLoopIteration() +{ + sync(_syncLoopTimeout); +} + void Connection::connectWithToken(const QString& userId, const QString& accessToken, const QString& deviceId) @@ -252,7 +256,6 @@ void Connection::Private::connectWithToken(const QString& user, << "by user" << userId << "from device" << deviceId; emit q->stateChanged(); emit q->connected(); - q->sync(); // initial sync after connection } void Connection::checkAndConnect(const QString& userId, @@ -321,6 +324,15 @@ void Connection::sync(int timeout) }); } +void Connection::syncLoop(int timeout) +{ + _syncLoopTimeout = timeout; + connect(this, &Connection::syncDone, this, &Connection::getNewEventsOnSyncDone); + connect(this, &Connection::syncError, this, &Connection::getNewEventsOnSyncError); + _syncLoopElapsedTimer.start(); + sync(_syncLoopTimeout); // initial sync to start the loop +} + void Connection::onSyncSuccess(SyncData &&data, bool fromCache) { d->data->setLastEvent(data.nextBatch()); for (auto&& roomData: data.takeRoomData()) @@ -410,11 +422,33 @@ void Connection::onSyncSuccess(SyncData &&data, bool fromCache) { void Connection::getNewEvents() { - // Borrowed the logic from Quiark's code in Tensor - // to cache not too aggressively and not on the first sync. - if (++_saveStateCounter % 17 == 2) - saveState(); - sync(30*1000); + int delay = minSyncLoopDelayMs() - _syncLoopElapsedTimer.restart(); + if (delay<0) { + delay = 0; + } + QTimer::singleShot(delay, this, &Connection::syncLoopIteration); +} + +void Connection::getNewEventsOnSyncDone() +{ + if (_prevSyncLoopIterationDone) { + _syncLoopAttemptNumber++; + } else { + _syncLoopAttemptNumber = 0; + } + emit syncAttemptNumberChanged(_syncLoopAttemptNumber); + getNewEvents(); +} + +void Connection::getNewEventsOnSyncError() +{ + if (_prevSyncLoopIterationDone) { + _syncLoopAttemptNumber = 0; + } else { + _syncLoopAttemptNumber++; + } + emit syncAttemptNumberChanged(_syncLoopAttemptNumber); + getNewEvents(); } void Connection::stopSync() @@ -436,6 +470,15 @@ PostReceiptJob* Connection::postReceipt(Room* room, RoomEvent* event) const return callApi(room->id(), "m.read", event->id()); } +void Connection::setMinSyncDelayMs(qint64 minSyncDelayMs) +{ + if (_minSyncLoopDelayMs == minSyncDelayMs) + return; + + _minSyncLoopDelayMs = minSyncDelayMs; + emit minSyncDelayMsChanged(_minSyncLoopDelayMs); +} + JoinRoomJob* Connection::joinRoom(const QString& roomAlias, const QStringList& serverNames) { @@ -1100,6 +1143,16 @@ user_factory_t Connection::userFactory() return _userFactory; } +qint64 Connection::minSyncLoopDelayMs() const +{ + return _minSyncLoopDelayMs; +} + +uint Connection::syncLoopAttemptNumber() const +{ + return _syncLoopAttemptNumber; +} + room_factory_t Connection::_roomFactory = defaultRoomFactory<>(); user_factory_t Connection::_userFactory = defaultUserFactory<>(); diff --git a/lib/connection.h b/lib/connection.h index dcc77824..ee7ad243 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -105,6 +106,8 @@ namespace QMatrixClient Q_PROPERTY(QUrl homeserver READ homeserver WRITE setHomeserver NOTIFY homeserverChanged) Q_PROPERTY(bool cacheState READ cacheState WRITE setCacheState NOTIFY cacheStateChanged) Q_PROPERTY(bool lazyLoading READ lazyLoading WRITE setLazyLoading NOTIFY lazyLoadingChanged) + Q_PROPERTY(qint64 minSyncLoopDelayMs READ minSyncLoopDelayMs WRITE setMinSyncDelayMs NOTIFY minSyncDelayMsChanged) + Q_PROPERTY(uint syncLoopAttemptNumber READ syncLoopAttemptNumber NOTIFY syncAttemptNumberChanged) public: // Room ids, rather than room pointers, are used in the direct chat @@ -353,6 +356,11 @@ namespace QMatrixClient template static void setUserType() { setUserFactory(defaultUserFactory()); } + qint64 minSyncLoopDelayMs() const; + void setMinSyncDelayMs(qint64 minSyncLoopDelayMs); + + uint syncLoopAttemptNumber() const; + public slots: /** Set the homeserver base URL */ void setHomeserver(const QUrl& baseUrl); @@ -371,6 +379,15 @@ namespace QMatrixClient void logout(); void sync(int timeout = -1); + + /** Start sync loop with the minSyncLoopDelayMs value + where minSyncLoopDelayMs could be changed on the client + according to syncDone/syncError signals and + the syncLoopAttemptNumber counter. + The syncLoopAttemptNumber counter is resetting + after non-repeating syncDone/syncError events*/ + void syncLoop(int timeout = -1); + void stopSync(); QString nextBatchToken() const; @@ -645,6 +662,8 @@ namespace QMatrixClient void cacheStateChanged(); void lazyLoadingChanged(); void turnServersChanged(const QJsonObject& servers); + void minSyncDelayMsChanged(qint64 minSyncLoopDelayMs); + void syncAttemptNumberChanged(uint syncLoopAttemptNumber); protected: /** @@ -678,7 +697,11 @@ namespace QMatrixClient * Completes loading sync data. */ void onSyncSuccess(SyncData &&data, bool fromCache = false); + + protected slots: void getNewEvents(); + void getNewEventsOnSyncDone(); + void getNewEventsOnSyncError(); private: class Private; @@ -704,7 +727,12 @@ namespace QMatrixClient static room_factory_t _roomFactory; static user_factory_t _userFactory; - int _saveStateCounter = 0; + QElapsedTimer _syncLoopElapsedTimer; + int _syncLoopTimeout = -1; + qint64 _minSyncLoopDelayMs = 0; + void syncLoopIteration(); + uint _syncLoopAttemptNumber = 0; + bool _prevSyncLoopIterationDone = false; }; } // namespace QMatrixClient Q_DECLARE_METATYPE(QMatrixClient::Connection*) -- cgit v1.2.3