aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Andreyev <aa13q@ya.ru>2019-02-02 23:51:20 +0300
committerAlexey Andreyev <aa13q@ya.ru>2019-02-03 11:07:36 +0300
commit22dd5f1e8988b03a691487cdad164a82a36e7f8c (patch)
treebbe8f5ce03e61e35f30a870fb9de06992ab07f72
parentcc7d034fa67196ad4950d3785aff64e4c5765855 (diff)
downloadlibquotient-22dd5f1e8988b03a691487cdad164a82a36e7f8c.tar.gz
libquotient-22dd5f1e8988b03a691487cdad164a82a36e7f8c.zip
Connection: separated sync loop logic with delay control
Signed-off-by: Alexey Andreyev <aa13q@ya.ru>
-rw-r--r--lib/connection.cpp69
-rw-r--r--lib/connection.h30
2 files changed, 90 insertions, 9 deletions
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 <QtCore/QRegularExpression>
#include <QtCore/QMimeDatabase>
#include <QtCore/QCoreApplication>
+#include <QTimer>
using namespace QMatrixClient;
@@ -133,8 +134,6 @@ Connection::Connection(const QUrl& server, QObject* parent)
, d(std::make_unique<Private>(std::make_unique<ConnectionData>(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<PostReceiptJob>(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 <QtCore/QObject>
#include <QtCore/QUrl>
#include <QtCore/QSize>
+#include <QElapsedTimer>
#include <functional>
#include <memory>
@@ -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 <typename T>
static void setUserType() { setUserFactory(defaultUserFactory<T>()); }
+ 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*)