diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-05-12 14:00:54 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2017-05-12 14:00:54 +0200 |
commit | d3cb4e649177443e8ecfd7f86d136fc0a319e2f3 (patch) | |
tree | 5a873b810944e1998b8f472db6c59fcc7e307863 | |
parent | 8730949269771ad4d6bba9ba2414d272f9a0a799 (diff) | |
download | sink-d3cb4e649177443e8ecfd7f86d136fc0a319e2f3.tar.gz sink-d3cb4e649177443e8ecfd7f86d136fc0a319e2f3.zip |
Don't add resources that don't match the query during a livequery
-rw-r--r-- | common/resourcefacade.cpp | 43 | ||||
-rw-r--r-- | common/resourcefacade.h | 18 | ||||
-rw-r--r-- | tests/querytest.cpp | 35 |
3 files changed, 75 insertions, 21 deletions
diff --git a/common/resourcefacade.cpp b/common/resourcefacade.cpp index e6f98a9..dab6aed 100644 --- a/common/resourcefacade.cpp +++ b/common/resourcefacade.cpp | |||
@@ -96,17 +96,24 @@ template<typename DomainType> | |||
96 | LocalStorageQueryRunner<DomainType>::LocalStorageQueryRunner(const Query &query, const QByteArray &identifier, const QByteArray &typeName, ConfigNotifier &configNotifier, const Sink::Log::Context &ctx) | 96 | LocalStorageQueryRunner<DomainType>::LocalStorageQueryRunner(const Query &query, const QByteArray &identifier, const QByteArray &typeName, ConfigNotifier &configNotifier, const Sink::Log::Context &ctx) |
97 | : mResultProvider(new ResultProvider<typename DomainType::Ptr>), mConfigStore(identifier, typeName), mGuard(new QObject), mLogCtx(ctx.subContext("config")) | 97 | : mResultProvider(new ResultProvider<typename DomainType::Ptr>), mConfigStore(identifier, typeName), mGuard(new QObject), mLogCtx(ctx.subContext("config")) |
98 | { | 98 | { |
99 | |||
100 | auto matchesTypeAndIds = [query, this] (const QByteArray &type, const QByteArray &id) { | ||
101 | if (query.hasFilter(ApplicationDomain::SinkResource::ResourceType::name) && query.getFilter(ApplicationDomain::SinkResource::ResourceType::name).value.toByteArray() != type) { | ||
102 | SinkTraceCtx(mLogCtx) << "Skipping due to type."; | ||
103 | return false; | ||
104 | } | ||
105 | if (!query.ids().isEmpty() && !query.ids().contains(id)) { | ||
106 | return false; | ||
107 | } | ||
108 | return true; | ||
109 | }; | ||
110 | |||
99 | QObject *guard = new QObject; | 111 | QObject *guard = new QObject; |
100 | mResultProvider->setFetcher([this, query, guard, &configNotifier](const QSharedPointer<DomainType> &) { | 112 | mResultProvider->setFetcher([this, query, guard, &configNotifier, matchesTypeAndIds](const QSharedPointer<DomainType> &) { |
101 | const auto entries = mConfigStore.getEntries(); | 113 | const auto entries = mConfigStore.getEntries(); |
102 | for (const auto &res : entries.keys()) { | 114 | for (const auto &res : entries.keys()) { |
103 | const auto type = entries.value(res); | 115 | const auto type = entries.value(res); |
104 | 116 | if (!matchesTypeAndIds(type, res)){ | |
105 | if (query.hasFilter(ApplicationDomain::SinkResource::ResourceType::name) && query.getFilter(ApplicationDomain::SinkResource::ResourceType::name).value.toByteArray() != type) { | ||
106 | SinkTraceCtx(mLogCtx) << "Skipping due to type."; | ||
107 | continue; | ||
108 | } | ||
109 | if (!query.ids().isEmpty() && !query.ids().contains(res)) { | ||
110 | continue; | 117 | continue; |
111 | } | 118 | } |
112 | auto entity = readFromConfig<DomainType>(mConfigStore, res, type, query.requestedProperties); | 119 | auto entity = readFromConfig<DomainType>(mConfigStore, res, type, query.requestedProperties); |
@@ -124,8 +131,14 @@ LocalStorageQueryRunner<DomainType>::LocalStorageQueryRunner(const Query &query, | |||
124 | }); | 131 | }); |
125 | if (query.liveQuery()) { | 132 | if (query.liveQuery()) { |
126 | { | 133 | { |
127 | auto ret = QObject::connect(&configNotifier, &ConfigNotifier::added, guard, [this](const ApplicationDomain::ApplicationDomainType::Ptr &entry) { | 134 | auto ret = QObject::connect(&configNotifier, &ConfigNotifier::added, guard, [this, query, matchesTypeAndIds](const ApplicationDomain::ApplicationDomainType::Ptr &entry, const QByteArray &type) { |
128 | auto entity = entry.staticCast<DomainType>(); | 135 | auto entity = entry.staticCast<DomainType>(); |
136 | if (!matchesTypeAndIds(type, entity->identifier())){ | ||
137 | return; | ||
138 | } | ||
139 | if (!matchesFilter(query.getBaseFilters(), *entity)){ | ||
140 | return; | ||
141 | } | ||
129 | SinkTraceCtx(mLogCtx) << "A new resource has been added: " << entity->identifier(); | 142 | SinkTraceCtx(mLogCtx) << "A new resource has been added: " << entity->identifier(); |
130 | updateStatus(*entity); | 143 | updateStatus(*entity); |
131 | mResultProvider->add(entity); | 144 | mResultProvider->add(entity); |
@@ -133,8 +146,14 @@ LocalStorageQueryRunner<DomainType>::LocalStorageQueryRunner(const Query &query, | |||
133 | Q_ASSERT(ret); | 146 | Q_ASSERT(ret); |
134 | } | 147 | } |
135 | { | 148 | { |
136 | auto ret = QObject::connect(&configNotifier, &ConfigNotifier::modified, guard, [this](const ApplicationDomain::ApplicationDomainType::Ptr &entry) { | 149 | auto ret = QObject::connect(&configNotifier, &ConfigNotifier::modified, guard, [this, query, matchesTypeAndIds](const ApplicationDomain::ApplicationDomainType::Ptr &entry, const QByteArray &type) { |
137 | auto entity = entry.staticCast<DomainType>(); | 150 | auto entity = entry.staticCast<DomainType>(); |
151 | if (!matchesTypeAndIds(type, entity->identifier())){ | ||
152 | return; | ||
153 | } | ||
154 | if (!matchesFilter(query.getBaseFilters(), *entity)){ | ||
155 | return; | ||
156 | } | ||
138 | updateStatus(*entity); | 157 | updateStatus(*entity); |
139 | mResultProvider->modify(entity); | 158 | mResultProvider->modify(entity); |
140 | }); | 159 | }); |
@@ -218,7 +237,7 @@ KAsync::Job<void> LocalStorageFacade<DomainType>::create(const DomainType &domai | |||
218 | } | 237 | } |
219 | configStore.modify(identifier, configurationValues); | 238 | configStore.modify(identifier, configurationValues); |
220 | } | 239 | } |
221 | sConfigNotifier.add(::readFromConfig<DomainType>(configStore, identifier, type, QByteArrayList{})); | 240 | sConfigNotifier.add(::readFromConfig<DomainType>(configStore, identifier, type, QByteArrayList{}), type); |
222 | }); | 241 | }); |
223 | } | 242 | } |
224 | 243 | ||
@@ -247,7 +266,7 @@ KAsync::Job<void> LocalStorageFacade<DomainType>::modify(const DomainType &domai | |||
247 | } | 266 | } |
248 | 267 | ||
249 | const auto type = configStore.getEntries().value(identifier); | 268 | const auto type = configStore.getEntries().value(identifier); |
250 | sConfigNotifier.modify(::readFromConfig<DomainType>(configStore, identifier, type, QByteArrayList{})); | 269 | sConfigNotifier.modify(::readFromConfig<DomainType>(configStore, identifier, type, QByteArrayList{}), type); |
251 | }); | 270 | }); |
252 | } | 271 | } |
253 | 272 | ||
@@ -277,7 +296,7 @@ KAsync::Job<void> LocalStorageFacade<DomainType>::remove(const DomainType &domai | |||
277 | SinkTrace() << "Removing: " << identifier; | 296 | SinkTrace() << "Removing: " << identifier; |
278 | auto configStore = ConfigStore(configStoreIdentifier, typeName); | 297 | auto configStore = ConfigStore(configStoreIdentifier, typeName); |
279 | configStore.remove(identifier); | 298 | configStore.remove(identifier); |
280 | sConfigNotifier.remove(QSharedPointer<DomainType>::create(domainObject)); | 299 | sConfigNotifier.remove(QSharedPointer<DomainType>::create(domainObject), typeName); |
281 | }); | 300 | }); |
282 | } | 301 | } |
283 | 302 | ||
diff --git a/common/resourcefacade.h b/common/resourcefacade.h index 1cc075c..76fadce 100644 --- a/common/resourcefacade.h +++ b/common/resourcefacade.h | |||
@@ -36,24 +36,24 @@ class ConfigNotifier : public QObject | |||
36 | { | 36 | { |
37 | Q_OBJECT | 37 | Q_OBJECT |
38 | public: | 38 | public: |
39 | void add(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account) | 39 | void add(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type) |
40 | { | 40 | { |
41 | emit added(account); | 41 | emit added(account, type); |
42 | } | 42 | } |
43 | 43 | ||
44 | void remove(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account) | 44 | void remove(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type) |
45 | { | 45 | { |
46 | emit removed(account); | 46 | emit removed(account, type); |
47 | } | 47 | } |
48 | 48 | ||
49 | void modify(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account) | 49 | void modify(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type) |
50 | { | 50 | { |
51 | emit modified(account); | 51 | emit modified(account, type); |
52 | } | 52 | } |
53 | signals: | 53 | signals: |
54 | void added(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account); | 54 | void added(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type); |
55 | void removed(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account); | 55 | void removed(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type); |
56 | void modified(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account); | 56 | void modified(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type); |
57 | }; | 57 | }; |
58 | 58 | ||
59 | template <typename DomainType> | 59 | template <typename DomainType> |
diff --git a/tests/querytest.cpp b/tests/querytest.cpp index 72eca86..4ff1be8 100644 --- a/tests/querytest.cpp +++ b/tests/querytest.cpp | |||
@@ -625,6 +625,41 @@ private slots: | |||
625 | // We fetch before the data is available and rely on the live query mechanism to deliver the actual data | 625 | // We fetch before the data is available and rely on the live query mechanism to deliver the actual data |
626 | auto folders = Sink::Store::read<Folder>(Sink::Query{}.resourceContainsFilter<SinkResource::Capabilities>("cap1")); | 626 | auto folders = Sink::Store::read<Folder>(Sink::Query{}.resourceContainsFilter<SinkResource::Capabilities>("cap1")); |
627 | QCOMPARE(folders.size(), 1); | 627 | QCOMPARE(folders.size(), 1); |
628 | |||
629 | //TODO this should be part of the regular cleanup between tests | ||
630 | VERIFYEXEC(Store::remove(resource1)); | ||
631 | VERIFYEXEC(Store::remove(resource2)); | ||
632 | } | ||
633 | |||
634 | void testFilteredLiveResourceSubQuery() | ||
635 | { | ||
636 | using namespace Sink; | ||
637 | using namespace Sink::ApplicationDomain; | ||
638 | |||
639 | //Setup | ||
640 | auto resource1 = ApplicationDomainType::createEntity<SinkResource>(); | ||
641 | resource1.setResourceType("sink.dummy"); | ||
642 | resource1.setCapabilities(QByteArrayList() << "cap1"); | ||
643 | VERIFYEXEC(Store::create(resource1)); | ||
644 | VERIFYEXEC(Store::create<Folder>(Folder{resource1.identifier()})); | ||
645 | VERIFYEXEC(ResourceControl::flushMessageQueue(resource1.identifier())); | ||
646 | |||
647 | auto model = Sink::Store::loadModel<Folder>(Query{Query::LiveQuery}.resourceContainsFilter<SinkResource::Capabilities>("cap1")); | ||
648 | QTRY_COMPARE(model->rowCount(), 1); | ||
649 | |||
650 | auto resource2 = ApplicationDomainType::createEntity<SinkResource>(); | ||
651 | resource2.setCapabilities(QByteArrayList() << "cap2"); | ||
652 | resource2.setResourceType("sink.dummy"); | ||
653 | VERIFYEXEC(Store::create(resource2)); | ||
654 | VERIFYEXEC(Store::create<Folder>(Folder{resource2.identifier()})); | ||
655 | VERIFYEXEC(ResourceControl::flushMessageQueue(resource2.identifier())); | ||
656 | |||
657 | //The new resource should be filtered and thus not make it in here | ||
658 | QCOMPARE(model->rowCount(), 1); | ||
659 | |||
660 | //TODO this should be part of the regular cleanup between tests | ||
661 | VERIFYEXEC(Store::remove(resource1)); | ||
662 | VERIFYEXEC(Store::remove(resource2)); | ||
628 | } | 663 | } |
629 | 664 | ||
630 | void testLivequeryUnmatchInThread() | 665 | void testLivequeryUnmatchInThread() |