From b11b8a774e83aa7de65758e814c3fabea87f6160 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 3 Feb 2017 16:54:56 +0100 Subject: Fixed incremental fetching --- common/resultprovider.h | 19 +++++++++++++------ tests/clientapitest.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/common/resultprovider.h b/common/resultprovider.h index 86138db..a2ed0b5 100644 --- a/common/resultprovider.h +++ b/common/resultprovider.h @@ -344,22 +344,25 @@ public: auto ptr = emitter.data(); emitter->onInitialResultSetComplete([this, ptr](const DomainType &parent, bool replayedAll) { auto hashValue = qHash(parent); + if (replayedAll) { + mAllResultsReplayed.remove(hashValue, ptr); + } mInitialResultSetInProgress.remove(hashValue, ptr); - callInitialResultCompleteIfDone(parent, replayedAll); + callInitialResultCompleteIfDone(parent); }); emitter->onComplete([this]() { this->complete(); }); emitter->onClear([this]() { this->clear(); }); mEmitter << emitter; } - void callInitialResultCompleteIfDone(const DomainType &parent, bool replayedAll) + void callInitialResultCompleteIfDone(const DomainType &parent) { auto hashValue = qHash(parent); // Normally a parent is only in a single resource, except the toplevel (invalid) parent if (!mInitialResultSetInProgress.contains(hashValue) && mAllResultsFetched && !mResultEmitted) { + bool allResourcesReplayedAll = mAllResultsReplayed.isEmpty(); mResultEmitted = true; - //FIXME set replayed all only to true if all had set it to true - this->initialResultSetComplete(parent, true); + this->initialResultSetComplete(parent, allResourcesReplayedAll); } } @@ -370,18 +373,22 @@ public: } else { mResultEmitted = false; mAllResultsFetched = false; + mAllResultsReplayed.clear(); + const auto hashValue = qHash(parent); for (const auto &emitter : mEmitter) { - mInitialResultSetInProgress.insert(qHash(parent), emitter.data()); + mInitialResultSetInProgress.insert(hashValue, emitter.data()); + mAllResultsReplayed.insert(hashValue, emitter.data()); emitter->fetch(parent); } mAllResultsFetched = true; - callInitialResultCompleteIfDone(parent, true); + callInitialResultCompleteIfDone(parent); } } private: QList::Ptr> mEmitter; QMultiMap *> mInitialResultSetInProgress; + QMultiMap *> mAllResultsReplayed; bool mAllResultsFetched; bool mResultEmitted; }; diff --git a/tests/clientapitest.cpp b/tests/clientapitest.cpp index 55fdcfc..fb1bdeb 100644 --- a/tests/clientapitest.cpp +++ b/tests/clientapitest.cpp @@ -69,13 +69,25 @@ public: SinkTraceCtx(ctx) << "Running the fetcher."; } SinkTraceCtx(ctx) << "-------------------------."; - for (const auto &res : results) { + int count = 0; + for (int i = offset; i < results.size(); i++) { + const auto res = results.at(i); + count++; // SinkTraceCtx(ctx) << "Parent filter " << query.getFilter("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray(); auto parentProperty = res->getProperty("parent").toByteArray(); if ((!parent && parentProperty.isEmpty()) || (parent && parentProperty == parent->identifier()) || query.parentProperty().isEmpty()) { // SinkTraceCtx(ctx) << "Found a hit" << res->identifier(); resultProvider->add(res); } + if (query.limit()) { + if (count >= query.limit()) { + SinkTraceCtx(ctx) << "Aborting early after " << count << "results."; + offset = i + 1; + bool fetchedAll = (i + 1 >= results.size()); + resultProvider->initialResultSetComplete(parent, fetchedAll); + return 0; + } + } } resultProvider->initialResultSetComplete(parent, true); return 0; @@ -89,6 +101,7 @@ public: QList results; Sink::ResultProviderInterface *mResultProvider; bool runAsync = false; + int offset = 0; }; @@ -285,6 +298,41 @@ private slots: QVERIFY(gotValue); } + void testMultiresourceIncrementalLoad() + { + auto facade1 = TestDummyResourceFacade::registerFacade("dummyresource.instance1"); + for (int i = 0; i < 4; i++) { + facade1->results << QSharedPointer::create("resource1", "id" + QByteArray::number(i), 0, QSharedPointer::create()); + } + auto facade2 = TestDummyResourceFacade::registerFacade("dummyresource.instance2"); + for (int i = 0; i < 6; i++) { + facade2->results << QSharedPointer::create("resource2", "id" + QByteArray::number(i), 0, QSharedPointer::create()); + } + ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); + ResourceConfig::addResource("dummyresource.instance2", "dummyresource"); + + Sink::Query query; + query.limit(2); + + auto model = Sink::Store::loadModel(query); + QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); + QCOMPARE(model->rowCount(QModelIndex()), 4); + + //Try to fetch another round + QVERIFY(model->canFetchMore(QModelIndex())); + model->fetchMore(QModelIndex()); + QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); + QCOMPARE(model->rowCount(QModelIndex()), 8); + + //Try to fetch the last round + QVERIFY(model->canFetchMore(QModelIndex())); + model->fetchMore(QModelIndex()); + QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); + QCOMPARE(model->rowCount(QModelIndex()), 10); + + QVERIFY(!model->canFetchMore(QModelIndex())); + } + void testModelStress() { auto facade = TestDummyResourceFacade::registerFacade(); -- cgit v1.2.3