diff options
-rw-r--r-- | common/resultprovider.h | 19 | ||||
-rw-r--r-- | 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: | |||
344 | auto ptr = emitter.data(); | 344 | auto ptr = emitter.data(); |
345 | emitter->onInitialResultSetComplete([this, ptr](const DomainType &parent, bool replayedAll) { | 345 | emitter->onInitialResultSetComplete([this, ptr](const DomainType &parent, bool replayedAll) { |
346 | auto hashValue = qHash(parent); | 346 | auto hashValue = qHash(parent); |
347 | if (replayedAll) { | ||
348 | mAllResultsReplayed.remove(hashValue, ptr); | ||
349 | } | ||
347 | mInitialResultSetInProgress.remove(hashValue, ptr); | 350 | mInitialResultSetInProgress.remove(hashValue, ptr); |
348 | callInitialResultCompleteIfDone(parent, replayedAll); | 351 | callInitialResultCompleteIfDone(parent); |
349 | }); | 352 | }); |
350 | emitter->onComplete([this]() { this->complete(); }); | 353 | emitter->onComplete([this]() { this->complete(); }); |
351 | emitter->onClear([this]() { this->clear(); }); | 354 | emitter->onClear([this]() { this->clear(); }); |
352 | mEmitter << emitter; | 355 | mEmitter << emitter; |
353 | } | 356 | } |
354 | 357 | ||
355 | void callInitialResultCompleteIfDone(const DomainType &parent, bool replayedAll) | 358 | void callInitialResultCompleteIfDone(const DomainType &parent) |
356 | { | 359 | { |
357 | auto hashValue = qHash(parent); | 360 | auto hashValue = qHash(parent); |
358 | // Normally a parent is only in a single resource, except the toplevel (invalid) parent | 361 | // Normally a parent is only in a single resource, except the toplevel (invalid) parent |
359 | if (!mInitialResultSetInProgress.contains(hashValue) && mAllResultsFetched && !mResultEmitted) { | 362 | if (!mInitialResultSetInProgress.contains(hashValue) && mAllResultsFetched && !mResultEmitted) { |
363 | bool allResourcesReplayedAll = mAllResultsReplayed.isEmpty(); | ||
360 | mResultEmitted = true; | 364 | mResultEmitted = true; |
361 | //FIXME set replayed all only to true if all had set it to true | 365 | this->initialResultSetComplete(parent, allResourcesReplayedAll); |
362 | this->initialResultSetComplete(parent, true); | ||
363 | } | 366 | } |
364 | } | 367 | } |
365 | 368 | ||
@@ -370,18 +373,22 @@ public: | |||
370 | } else { | 373 | } else { |
371 | mResultEmitted = false; | 374 | mResultEmitted = false; |
372 | mAllResultsFetched = false; | 375 | mAllResultsFetched = false; |
376 | mAllResultsReplayed.clear(); | ||
377 | const auto hashValue = qHash(parent); | ||
373 | for (const auto &emitter : mEmitter) { | 378 | for (const auto &emitter : mEmitter) { |
374 | mInitialResultSetInProgress.insert(qHash(parent), emitter.data()); | 379 | mInitialResultSetInProgress.insert(hashValue, emitter.data()); |
380 | mAllResultsReplayed.insert(hashValue, emitter.data()); | ||
375 | emitter->fetch(parent); | 381 | emitter->fetch(parent); |
376 | } | 382 | } |
377 | mAllResultsFetched = true; | 383 | mAllResultsFetched = true; |
378 | callInitialResultCompleteIfDone(parent, true); | 384 | callInitialResultCompleteIfDone(parent); |
379 | } | 385 | } |
380 | } | 386 | } |
381 | 387 | ||
382 | private: | 388 | private: |
383 | QList<typename ResultEmitter<DomainType>::Ptr> mEmitter; | 389 | QList<typename ResultEmitter<DomainType>::Ptr> mEmitter; |
384 | QMultiMap<qint64, ResultEmitter<DomainType> *> mInitialResultSetInProgress; | 390 | QMultiMap<qint64, ResultEmitter<DomainType> *> mInitialResultSetInProgress; |
391 | QMultiMap<qint64, ResultEmitter<DomainType> *> mAllResultsReplayed; | ||
385 | bool mAllResultsFetched; | 392 | bool mAllResultsFetched; |
386 | bool mResultEmitted; | 393 | bool mResultEmitted; |
387 | }; | 394 | }; |
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: | |||
69 | SinkTraceCtx(ctx) << "Running the fetcher."; | 69 | SinkTraceCtx(ctx) << "Running the fetcher."; |
70 | } | 70 | } |
71 | SinkTraceCtx(ctx) << "-------------------------."; | 71 | SinkTraceCtx(ctx) << "-------------------------."; |
72 | for (const auto &res : results) { | 72 | int count = 0; |
73 | for (int i = offset; i < results.size(); i++) { | ||
74 | const auto res = results.at(i); | ||
75 | count++; | ||
73 | // SinkTraceCtx(ctx) << "Parent filter " << query.getFilter("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray(); | 76 | // SinkTraceCtx(ctx) << "Parent filter " << query.getFilter("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray(); |
74 | auto parentProperty = res->getProperty("parent").toByteArray(); | 77 | auto parentProperty = res->getProperty("parent").toByteArray(); |
75 | if ((!parent && parentProperty.isEmpty()) || (parent && parentProperty == parent->identifier()) || query.parentProperty().isEmpty()) { | 78 | if ((!parent && parentProperty.isEmpty()) || (parent && parentProperty == parent->identifier()) || query.parentProperty().isEmpty()) { |
76 | // SinkTraceCtx(ctx) << "Found a hit" << res->identifier(); | 79 | // SinkTraceCtx(ctx) << "Found a hit" << res->identifier(); |
77 | resultProvider->add(res); | 80 | resultProvider->add(res); |
78 | } | 81 | } |
82 | if (query.limit()) { | ||
83 | if (count >= query.limit()) { | ||
84 | SinkTraceCtx(ctx) << "Aborting early after " << count << "results."; | ||
85 | offset = i + 1; | ||
86 | bool fetchedAll = (i + 1 >= results.size()); | ||
87 | resultProvider->initialResultSetComplete(parent, fetchedAll); | ||
88 | return 0; | ||
89 | } | ||
90 | } | ||
79 | } | 91 | } |
80 | resultProvider->initialResultSetComplete(parent, true); | 92 | resultProvider->initialResultSetComplete(parent, true); |
81 | return 0; | 93 | return 0; |
@@ -89,6 +101,7 @@ public: | |||
89 | QList<typename T::Ptr> results; | 101 | QList<typename T::Ptr> results; |
90 | Sink::ResultProviderInterface<typename T::Ptr> *mResultProvider; | 102 | Sink::ResultProviderInterface<typename T::Ptr> *mResultProvider; |
91 | bool runAsync = false; | 103 | bool runAsync = false; |
104 | int offset = 0; | ||
92 | }; | 105 | }; |
93 | 106 | ||
94 | 107 | ||
@@ -285,6 +298,41 @@ private slots: | |||
285 | QVERIFY(gotValue); | 298 | QVERIFY(gotValue); |
286 | } | 299 | } |
287 | 300 | ||
301 | void testMultiresourceIncrementalLoad() | ||
302 | { | ||
303 | auto facade1 = TestDummyResourceFacade<Sink::ApplicationDomain::Event>::registerFacade("dummyresource.instance1"); | ||
304 | for (int i = 0; i < 4; i++) { | ||
305 | facade1->results << QSharedPointer<Sink::ApplicationDomain::Event>::create("resource1", "id" + QByteArray::number(i), 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
306 | } | ||
307 | auto facade2 = TestDummyResourceFacade<Sink::ApplicationDomain::Event>::registerFacade("dummyresource.instance2"); | ||
308 | for (int i = 0; i < 6; i++) { | ||
309 | facade2->results << QSharedPointer<Sink::ApplicationDomain::Event>::create("resource2", "id" + QByteArray::number(i), 0, QSharedPointer<Sink::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
310 | } | ||
311 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | ||
312 | ResourceConfig::addResource("dummyresource.instance2", "dummyresource"); | ||
313 | |||
314 | Sink::Query query; | ||
315 | query.limit(2); | ||
316 | |||
317 | auto model = Sink::Store::loadModel<Sink::ApplicationDomain::Event>(query); | ||
318 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | ||
319 | QCOMPARE(model->rowCount(QModelIndex()), 4); | ||
320 | |||
321 | //Try to fetch another round | ||
322 | QVERIFY(model->canFetchMore(QModelIndex())); | ||
323 | model->fetchMore(QModelIndex()); | ||
324 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | ||
325 | QCOMPARE(model->rowCount(QModelIndex()), 8); | ||
326 | |||
327 | //Try to fetch the last round | ||
328 | QVERIFY(model->canFetchMore(QModelIndex())); | ||
329 | model->fetchMore(QModelIndex()); | ||
330 | QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); | ||
331 | QCOMPARE(model->rowCount(QModelIndex()), 10); | ||
332 | |||
333 | QVERIFY(!model->canFetchMore(QModelIndex())); | ||
334 | } | ||
335 | |||
288 | void testModelStress() | 336 | void testModelStress() |
289 | { | 337 | { |
290 | auto facade = TestDummyResourceFacade<Sink::ApplicationDomain::Folder>::registerFacade(); | 338 | auto facade = TestDummyResourceFacade<Sink::ApplicationDomain::Folder>::registerFacade(); |