File indexing completed on 2024-05-12 05:26:02

0001 /*
0002     Copyright (c) 2015 Christian Mollekopf <mollekopf@kolabsys.com>
0003 
0004     This library is free software; you can redistribute it and/or modify it
0005     under the terms of the GNU Library General Public License as published by
0006     the Free Software Foundation; either version 2 of the License, or (at your
0007     option) any later version.
0008 
0009     This library is distributed in the hope that it will be useful, but WITHOUT
0010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
0012     License for more details.
0013 
0014     You should have received a copy of the GNU Library General Public License
0015     along with this library; see the file COPYING.LIB.  If not, write to the
0016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0017     02110-1301, USA.
0018 */
0019 
0020 #pragma once
0021 
0022 #include <QObject>
0023 #include "resourcecontext.h"
0024 #include "resultprovider.h"
0025 #include "query.h"
0026 #include "log.h"
0027 #include "datastorequery.h"
0028 
0029 /**
0030  * Base clase because you can't have the Q_OBJECT macro in template classes
0031  */
0032 class QueryRunnerBase : public QObject
0033 {
0034     Q_OBJECT
0035 public:
0036     typedef std::function<void(Sink::ApplicationDomain::ApplicationDomainType &domainObject)> ResultTransformation;
0037 
0038     /// Disable query updates on revision change. Used for testing only.
0039     void ignoreRevisionChanges() {
0040         mIgnoreRevisionChanges = true;
0041     }
0042 
0043     /// Manually triger a revision change. Used for testing only.
0044     void triggerRevisionChange() {
0045         mIgnoreRevisionChanges = false;
0046         revisionChanged();
0047     }
0048 
0049 protected:
0050     typedef std::function<KAsync::Job<void>()> QueryFunction;
0051 
0052     /**
0053      * Set the query to run
0054      */
0055     void setQuery(const QueryFunction &query)
0056     {
0057         queryFunction = query;
0058     }
0059 
0060 protected slots:
0061     /**
0062      * Rerun query with new revision
0063      */
0064     void revisionChanged()
0065     {
0066         if (!mIgnoreRevisionChanges) {
0067             run().exec();
0068         }
0069     }
0070 
0071 private:
0072     /**
0073      * Starts query
0074      */
0075     KAsync::Job<void> run()
0076     {
0077         return queryFunction();
0078     }
0079 
0080     QueryFunction queryFunction;
0081     bool mIgnoreRevisionChanges{false};
0082 };
0083 
0084 /**
0085  * A QueryRunner runs a query and updates the corresponding result set.
0086  *
0087  * The lifetime of the QueryRunner is defined by the resut set (otherwise it's doing useless work),
0088  * and by how long a result set must be updated. If the query is a one off, the runner dies after the execution,
0089  * otherwise it lives on to react to changes, and updates the corresponding result set.
0090  *
0091  * QueryRunner has to keep ResourceAccess alive in order to keep getting updates.
0092  */
0093 template <typename DomainType>
0094 class SINK_EXPORT QueryRunner : public QueryRunnerBase
0095 {
0096 public:
0097     QueryRunner(const Sink::Query &query, const Sink::ResourceContext &context, const QByteArray &bufferType, const Sink::Log::Context &logCtx);
0098     virtual ~QueryRunner();
0099 
0100     /**
0101      * Allows you to run a transformation on every result.
0102      * This transformation is executed in the query thread.
0103      */
0104     void setResultTransformation(const ResultTransformation &transformation);
0105 
0106     typename Sink::ResultEmitter<typename DomainType::Ptr>::Ptr emitter();
0107 
0108     /**
0109      * For testing only.
0110      */
0111     void delayNextQuery();
0112 
0113 private:
0114     void fetch(const Sink::Query &query, const QByteArray &bufferType);
0115     KAsync::Job<void> incrementalFetch(const Sink::Query &query, const QByteArray &bufferType);
0116 
0117     Sink::ResourceContext mResourceContext;
0118     QSharedPointer<Sink::ResourceAccessInterface> mResourceAccess;
0119     QSharedPointer<Sink::ResultProvider<typename DomainType::Ptr>> mResultProvider;
0120     ResultTransformation mResultTransformation;
0121     DataStoreQuery::State::Ptr mQueryState;
0122     int mBatchSize;
0123     QObject guard;
0124     Sink::Log::Context mLogCtx;
0125     bool mInitialQueryComplete = false;
0126     bool mQueryInProgress = false;
0127     bool mRequestFetchMore = false;
0128     bool mDelayNextQuery = false;
0129     bool mRevisionChangedMeanwhile = false;
0130 };