summaryrefslogtreecommitdiffstats
path: root/common/clientapi.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2015-11-27 17:30:04 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2015-11-27 17:30:04 +0100
commit5b41b26a349967acf2197f9f9228526193fd826e (patch)
tree166452bcc0757564deefe233bf031d2ccb0564d2 /common/clientapi.cpp
parent13af56e436f49df32d3b2f6f223cf1dec2eabaac (diff)
downloadsink-5b41b26a349967acf2197f9f9228526193fd826e.tar.gz
sink-5b41b26a349967acf2197f9f9228526193fd826e.zip
Introduced a QueryRunner object
The QueryRunner object lives for the duration of the query (so just for the initial query for non-live queries, and for the lifetime of the result model for live queries). It's supposed to handle all the threading internally and decouple the lifetime of the facade.
Diffstat (limited to 'common/clientapi.cpp')
-rw-r--r--common/clientapi.cpp62
1 files changed, 17 insertions, 45 deletions
diff --git a/common/clientapi.cpp b/common/clientapi.cpp
index 02f8ce6..b24dfa8 100644
--- a/common/clientapi.cpp
+++ b/common/clientapi.cpp
@@ -34,6 +34,7 @@
34#include "definitions.h" 34#include "definitions.h"
35#include "resourceconfig.h" 35#include "resourceconfig.h"
36#include "facadefactory.h" 36#include "facadefactory.h"
37#include "modelresult.h"
37#include "log.h" 38#include "log.h"
38 39
39#define ASYNCINTHREAD 40#define ASYNCINTHREAD
@@ -100,38 +101,8 @@ template <class DomainType>
100QSharedPointer<ResultEmitter<typename DomainType::Ptr> > Store::load(Query query) 101QSharedPointer<ResultEmitter<typename DomainType::Ptr> > Store::load(Query query)
101{ 102{
102 auto resultSet = QSharedPointer<ResultProvider<typename DomainType::Ptr> >::create(); 103 auto resultSet = QSharedPointer<ResultProvider<typename DomainType::Ptr> >::create();
103 104 qWarning() << "Main thread " << QThread::currentThreadId();
104 //Execute the search in a thread. 105 //FIXME remove
105 //We must guarantee that the emitter is returned before the first result is emitted.
106 //The result provider must be threadsafe.
107 async::run([query, resultSet](){
108 QEventLoop eventLoop;
109 resultSet->onDone([&eventLoop](){
110 eventLoop.quit();
111 });
112 // Query all resources and aggregate results
113 KAsync::iterate(getResources(query.resources, ApplicationDomain::getTypeName<DomainType>()))
114 .template each<void, QByteArray>([query, resultSet](const QByteArray &resource, KAsync::Future<void> &future) {
115 if (auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource)) {
116 facade->load(query, *resultSet).template then<void>([&future](){future.setFinished();}).exec();
117 //Keep the facade alive for the lifetime of the resultSet.
118 resultSet->setFacade(facade);
119 } else {
120 //Ignore the error and carry on
121 future.setFinished();
122 }
123 }).template then<void>([query, resultSet]() {
124 resultSet->initialResultSetComplete();
125 if (!query.liveQuery) {
126 resultSet->complete();
127 }
128 }).exec();
129
130 //Keep the thread alive until the result is ready
131 if (!resultSet->isDone()) {
132 eventLoop.exec();
133 }
134 });
135 return resultSet->emitter(); 106 return resultSet->emitter();
136} 107}
137 108
@@ -139,28 +110,29 @@ template <class DomainType>
139QSharedPointer<QAbstractItemModel> Store::loadModel(Query query) 110QSharedPointer<QAbstractItemModel> Store::loadModel(Query query)
140{ 111{
141 auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr> >::create(query, query.requestedProperties.toList()); 112 auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr> >::create(query, query.requestedProperties.toList());
142 auto resultProvider = std::make_shared<ModelResultProvider<DomainType, typename DomainType::Ptr> >(model); 113
143 //Keep the resultprovider alive for as long as the model lives 114 //* Client defines lifetime of model
144 model->setProperty("resultProvider", QVariant::fromValue(std::shared_ptr<void>(resultProvider))); 115 //* The model lifetime defines the duration of live-queries
116 //* The facade needs to life for the duration of any calls being made (assuming we get rid of any internal callbacks
117 //* The emitter needs to live or the duration of query (respectively, the model)
118 //* The result provider needs to live for as long as results are provided (until the last thread exits).
145 119
146 // Query all resources and aggregate results 120 // Query all resources and aggregate results
147 KAsync::iterate(getResources(query.resources, ApplicationDomain::getTypeName<DomainType>())) 121 KAsync::iterate(getResources(query.resources, ApplicationDomain::getTypeName<DomainType>()))
148 .template each<void, QByteArray>([query, resultProvider](const QByteArray &resource, KAsync::Future<void> &future) { 122 .template each<void, QByteArray>([query, model](const QByteArray &resource, KAsync::Future<void> &future) {
149 auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource); 123 auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource);
150 if (facade) { 124 if (facade) {
151 facade->load(query, *resultProvider).template then<void>([&future](){future.setFinished();}).exec(); 125 Trace() << "Trying to fetch from resource";
152 //Keep the facade alive for the lifetime of the resultSet. 126 auto result = facade->load(query);
153 //FIXME this would have to become a list 127 auto emitter = result.second;
154 resultProvider->setFacade(facade); 128 //TODO use aggregating emitter instead
129 model->setEmitter(emitter);
130 model->fetchMore(QModelIndex());
131 result.first.template then<void>([&future](){future.setFinished();}).exec();
155 } else { 132 } else {
156 //Ignore the error and carry on 133 //Ignore the error and carry on
157 future.setFinished(); 134 future.setFinished();
158 } 135 }
159 }).template then<void>([query, resultProvider]() {
160 resultProvider->initialResultSetComplete();
161 if (!query.liveQuery) {
162 resultProvider->complete();
163 }
164 }).exec(); 136 }).exec();
165 137
166 return model; 138 return model;