From aacc4bcb4a487871daae6717f77605aaba444341 Mon Sep 17 00:00:00 2001 From: Marc Deop Date: Sat, 2 Mar 2019 12:26:57 +0100 Subject: style: apply .clang-format to all .cpp and .h files --- lib/connectiondata.cpp | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) (limited to 'lib/connectiondata.cpp') diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index eb516ef7..513e497e 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -13,19 +13,18 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "connectiondata.h" -#include "networkaccessmanager.h" #include "logging.h" +#include "networkaccessmanager.h" using namespace QMatrixClient; -struct ConnectionData::Private -{ - explicit Private(const QUrl& url) : baseUrl(url) { } +struct ConnectionData::Private { + explicit Private(const QUrl& url) : baseUrl(url) {} QUrl baseUrl; QByteArray accessToken; @@ -38,19 +37,14 @@ struct ConnectionData::Private ConnectionData::ConnectionData(QUrl baseUrl) : d(std::make_unique(baseUrl)) -{ } +{ +} ConnectionData::~ConnectionData() = default; -QByteArray ConnectionData::accessToken() const -{ - return d->accessToken; -} +QByteArray ConnectionData::accessToken() const { return d->accessToken; } -QUrl ConnectionData::baseUrl() const -{ - return d->baseUrl; -} +QUrl ConnectionData::baseUrl() const { return d->baseUrl; } QNetworkAccessManager* ConnectionData::nam() const { @@ -80,10 +74,7 @@ void ConnectionData::setPort(int port) qCDebug(MAIN) << "updated baseUrl to" << d->baseUrl; } -const QString& ConnectionData::deviceId() const -{ - return d->deviceId; -} +const QString& ConnectionData::deviceId() const { return d->deviceId; } void ConnectionData::setDeviceId(const QString& deviceId) { @@ -91,10 +82,7 @@ void ConnectionData::setDeviceId(const QString& deviceId) qCDebug(MAIN) << "updated deviceId to" << d->deviceId; } -QString ConnectionData::lastEvent() const -{ - return d->lastEvent; -} +QString ConnectionData::lastEvent() const { return d->lastEvent; } void ConnectionData::setLastEvent(QString identifier) { @@ -103,6 +91,6 @@ void ConnectionData::setLastEvent(QString identifier) QByteArray ConnectionData::generateTxnId() const { - return QByteArray::number(d->id) + 'q' + - QByteArray::number(++d->txnCounter); + return QByteArray::number(d->id) + 'q' + + QByteArray::number(++d->txnCounter); } -- cgit v1.2.3 From c05ade838f0fce81f2bbe80a3295618a8a26ff52 Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Fri, 2 Aug 2019 19:59:40 +0900 Subject: Apply the new brace wrapping to source files --- lib/connectiondata.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'lib/connectiondata.cpp') diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index c157565f..df4cece2 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -23,11 +23,8 @@ using namespace QMatrixClient; -struct ConnectionData::Private -{ - explicit Private(QUrl url) - : baseUrl(std::move(url)) - {} +struct ConnectionData::Private { + explicit Private(QUrl url) : baseUrl(std::move(url)) {} QUrl baseUrl; QByteArray accessToken; -- cgit v1.2.3 From 27ca32a1e5a56e09b9cc1d94224d2831004dcf3d Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Sun, 7 Jul 2019 19:32:34 +0900 Subject: Namespace: QMatrixClient -> Quotient (with back comp alias) --- lib/connectiondata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/connectiondata.cpp') diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index df4cece2..486de03d 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -21,7 +21,7 @@ #include "logging.h" #include "networkaccessmanager.h" -using namespace QMatrixClient; +using namespace Quotient; struct ConnectionData::Private { explicit Private(QUrl url) : baseUrl(std::move(url)) {} -- cgit v1.2.3 From 8629748c5c609882486d25d989becfe0ae2352ed Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 20 Aug 2019 17:59:27 +0900 Subject: Store userId in ConnectionData instead of Connection To collect all connection-identifying information in a single place. --- lib/connectiondata.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/connectiondata.cpp') diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index 486de03d..41d97b87 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -29,10 +29,11 @@ struct ConnectionData::Private { QUrl baseUrl; QByteArray accessToken; QString lastEvent; + QString userId; QString deviceId; mutable unsigned int txnCounter = 0; - const qint64 id = QDateTime::currentMSecsSinceEpoch(); + const qint64 txnBase = QDateTime::currentMSecsSinceEpoch(); }; ConnectionData::ConnectionData(QUrl baseUrl) @@ -75,12 +76,15 @@ void ConnectionData::setPort(int port) const QString& ConnectionData::deviceId() const { return d->deviceId; } +const QString& ConnectionData::userId() const { return d->userId; } + void ConnectionData::setDeviceId(const QString& deviceId) { d->deviceId = deviceId; - qCDebug(MAIN) << "updated deviceId to" << d->deviceId; } +void ConnectionData::setUserId(const QString& userId) { d->userId = userId; } + QString ConnectionData::lastEvent() const { return d->lastEvent; } void ConnectionData::setLastEvent(QString identifier) @@ -90,5 +94,6 @@ void ConnectionData::setLastEvent(QString identifier) QByteArray ConnectionData::generateTxnId() const { - return QByteArray::number(d->id) + 'q' + QByteArray::number(++d->txnCounter); + return d->deviceId.toLatin1() + QByteArray::number(d->txnBase) + + QByteArray::number(++d->txnCounter); } -- cgit v1.2.3 From 59c4996a602e9eeae4e3bfc0210ff15f957df38f Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Tue, 20 Aug 2019 20:09:09 +0900 Subject: BaseJob/ConnectionData: connection-wide rate-limiting As before, completely transparent for clients, driven by 529 errors from the server (but cases of rate limiting are signalled by BaseJob::rateLimited). That brings changes to BaseJob API: timeouts now use int64_t and also can be handled in std::chrono terms; aboutToStart() -> aboutToSendRequest(); started() -> sentRequest(). Closes #292. --- lib/connectiondata.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 3 deletions(-) (limited to 'lib/connectiondata.cpp') diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index 41d97b87..e241e376 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -20,11 +20,21 @@ #include "logging.h" #include "networkaccessmanager.h" +#include "jobs/basejob.h" + +#include +#include + +#include using namespace Quotient; -struct ConnectionData::Private { - explicit Private(QUrl url) : baseUrl(std::move(url)) {} +class ConnectionData::Private { +public: + explicit Private(QUrl url) : baseUrl(std::move(url)) + { + rateLimiter.setSingleShot(true); + } QUrl baseUrl; QByteArray accessToken; @@ -34,14 +44,68 @@ struct ConnectionData::Private { mutable unsigned int txnCounter = 0; const qint64 txnBase = QDateTime::currentMSecsSinceEpoch(); + + QString id() const { return userId + '/' + deviceId; } + + using job_queue_t = std::queue>; + std::array jobs; // 0 - foreground, 1 - background + QTimer rateLimiter; }; ConnectionData::ConnectionData(QUrl baseUrl) : d(std::make_unique(std::move(baseUrl))) -{} +{ + // Each lambda invocation below takes no more than one job from the + // queues (first foreground, then background) and resumes it; then + // restarts the rate limiter timer with duration 0, effectively yielding + // to the event loop and then resuming until both queues are empty. + QObject::connect(&d->rateLimiter, &QTimer::timeout, [this] { + // TODO: Consider moving out all job->sendRequest() invocations to + // a dedicated thread + d->rateLimiter.setInterval(0); + for (auto& q : d->jobs) + while (!q.empty()) { + auto& job = q.front(); + q.pop(); + if (!job || job->error() == BaseJob::Abandoned) + continue; + if (job->error() != BaseJob::Pending) { + qCCritical(MAIN) + << "Job" << job + << "is in the wrong status:" << job->status(); + Q_ASSERT(false); + job->setStatus(BaseJob::Pending); + } + job->sendRequest(); + d->rateLimiter.start(); + return; + } + qCDebug(MAIN) << d->id() << "job queues are empty"; + }); +} ConnectionData::~ConnectionData() = default; +void ConnectionData::submit(BaseJob* job) +{ + Q_ASSERT(job->error() == BaseJob::Pending); + if (!d->rateLimiter.isActive()) { + job->sendRequest(); + return; + } + d->jobs[size_t(job->isBackground())].emplace(job); + qCDebug(MAIN) << job << "queued," << d->jobs.front().size() << "+" + << d->jobs.back().size() << "total jobs in" << d->id() + << "queues"; +} + +void ConnectionData::limitRate(std::chrono::milliseconds nextCallAfter) +{ + qCDebug(MAIN) << "Jobs for" << (d->userId + "/" + d->deviceId) + << "suspended for" << nextCallAfter.count() << "ms"; + d->rateLimiter.start(nextCallAfter); +} + QByteArray ConnectionData::accessToken() const { return d->accessToken; } QUrl ConnectionData::baseUrl() const { return d->baseUrl; } -- cgit v1.2.3 From d803b04d37e82dd7f8b901d29e04851d97d1f4eb Mon Sep 17 00:00:00 2001 From: Kitsune Ral Date: Wed, 21 Aug 2019 15:18:20 +0900 Subject: Tighten the code; add a missing #include MSVC warns on class/struct mismatch and errors on std::array because `` is not indirectly included on that platform. --- lib/connectiondata.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/connectiondata.cpp') diff --git a/lib/connectiondata.cpp b/lib/connectiondata.cpp index e241e376..a3807fc4 100644 --- a/lib/connectiondata.cpp +++ b/lib/connectiondata.cpp @@ -25,6 +25,7 @@ #include #include +#include #include using namespace Quotient; -- cgit v1.2.3