diff options
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; |