diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-11-27 17:30:04 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2015-11-27 17:30:04 +0100 |
commit | 5b41b26a349967acf2197f9f9228526193fd826e (patch) | |
tree | 166452bcc0757564deefe233bf031d2ccb0564d2 /common/clientapi.cpp | |
parent | 13af56e436f49df32d3b2f6f223cf1dec2eabaac (diff) | |
download | sink-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.cpp | 62 |
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> | |||
100 | QSharedPointer<ResultEmitter<typename DomainType::Ptr> > Store::load(Query query) | 101 | QSharedPointer<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> | |||
139 | QSharedPointer<QAbstractItemModel> Store::loadModel(Query query) | 110 | QSharedPointer<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; |