コード例 #1
0
        /// <summary>
        /// Executes the <see cref="IQueryRequest"/> against the Couchbase server asynchronously.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queryRequest">The query request.</param>
        /// <param name="cancellationToken">Token which can cancel the query.</param>
        /// <returns></returns>
        public async Task <IQueryResult <T> > QueryAsync <T>(IQueryRequest queryRequest, CancellationToken cancellationToken)
        {
            //shortcut for adhoc requests
            if (queryRequest.IsAdHoc)
            {
                return(await ExecuteQueryAsync <T>(queryRequest, cancellationToken).ContinueOnAnyContext());
            }

            //optimize, return an error result if optimization step cannot complete
            try
            {
                await PrepareStatementIfNotAdHocAsync(queryRequest, cancellationToken).ContinueOnAnyContext();
            }
            catch (Exception e)
            {
                var errorResult = new QueryResult <T>();
                ProcessError(e, errorResult);
                return(errorResult);
            }

            // execute optimized query
            var result = await ExecuteQueryAsync <T>(queryRequest, cancellationToken).ContinueOnAnyContext();

            // if the query failed, check if the query plan should be evicted
            if (!result.Success && result.IsQueryPlanStale())
            {
                var originalStatement = queryRequest.GetOriginalStatement();
                _queryCache.TryRemove(originalStatement, out QueryPlan _);
            }

            return(result);
        }
コード例 #2
0
        /// <summary>
        /// Prepares the statement if the <see cref="IQueryRequest"/> is not ad-hoc and caches it for reuse.asynchronously.
        /// </summary>
        /// <param name="originalRequest">The original query request.</param>
        /// <param name="cancellationToken">Token which can cancel the query.</param>
        private async Task PrepareStatementIfNotAdHocAsync(IQueryRequest originalRequest, CancellationToken cancellationToken)
        {
            if (originalRequest.IsAdHoc)
            {
                return;
            }

            var originalStatement = originalRequest.GetOriginalStatement();

            if (_queryCache.TryGetValue(originalStatement, out var queryPlan))
            {
                originalRequest.Prepared(queryPlan, originalStatement);
            }
            else
            {
                var result = await PrepareAsync(originalRequest, cancellationToken).ContinueOnAnyContext();

                if (!result.Success)
                {
                    throw new PrepareStatementException("Unable to optimize async statement: " + result.GetErrorsAsString());
                }
                queryPlan = result.FirstOrDefault();
                if (queryPlan != null && _queryCache.TryAdd(originalStatement, queryPlan))
                {
                    originalRequest.Prepared(queryPlan, originalStatement);
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Prepares the statement if the <see cref="IQueryRequest"/> is not ad-hoc and caches it for reuse.asynchronously.
        /// </summary>
        /// <param name="originalRequest">The original query request.</param>
        async Task PrepareStatementIfNotAdHocAsync(IQueryRequest originalRequest)
        {
            if (originalRequest.IsAdHoc)
            {
                return;
            }

            var       originalStatement = originalRequest.GetOriginalStatement();
            QueryPlan queryPlan;

            if (_queryCache.TryGetValue(originalStatement, out queryPlan))
            {
                originalRequest.Prepared(queryPlan, originalStatement);
            }
            else
            {
                var result = await PrepareAsync(originalRequest);

                if (!result.Success)
                {
                    Log.WarnFormat("Failure to prepare async plan for query {0} (it will be reattempted next time it is issued): {1}",
                                   originalStatement, result.GetErrorsAsString());
                    throw new PrepareStatementException("Unable to optimize async statement: " + result.GetErrorsAsString());
                }
                queryPlan = result.Rows.FirstOrDefault();
                if (queryPlan != null && _queryCache.TryAdd(originalStatement, queryPlan))
                {
                    originalRequest.Prepared(queryPlan, originalStatement);
                }
            }
        }
コード例 #4
0
 internal static ISpanBuilder BuildSpan(this ITracer tracer, IQueryRequest query, string operationName)
 {
     return(tracer.BuildSpan(operationName)
            .WithTag(CouchbaseTags.OperationId, query.CurrentContextId)
            .WithTag(CouchbaseTags.Service, CouchbaseTags.ServiceN1ql)
            .WithTag(Tags.DbStatement, query.GetOriginalStatement())
            .AsChildOf(query.ActiveSpan));
 }
コード例 #5
0
 /// <summary>
 /// Prepare an ad-hoc N1QL statement for later execution against a Couchbase Server.
 /// </summary>
 /// <param name="toPrepare">The <see cref="IQueryRequest" /> containing a N1QL statement to be prepared.</param>
 /// <returns>
 /// A <see cref="IQueryResult{T}" /> containing  the <see cref="QueryPlan" /> representing the reusable
 /// and cachable execution plan for the statement.
 /// </returns>
 /// <remarks>
 /// Most parameters in the IQueryRequest will be ignored, appart from the Statement and the BaseUri.
 /// </remarks>
 public IQueryResult<QueryPlan> Prepare(IQueryRequest toPrepare)
 {
     var statement = toPrepare.GetOriginalStatement();
     if (!statement.ToUpper().StartsWith("PREPARE "))
     {
         statement = string.Concat("PREPARE ", statement);
     }
     var query = new QueryRequest(statement);
     query.BaseUri(toPrepare.GetBaseUri());
     return ExecuteQuery<QueryPlan>(query);
 }
コード例 #6
0
 /// <summary>
 /// Prepare an ad-hoc N1QL statement for later execution against a Couchbase Server asynchronously
 /// </summary>
 /// <param name="toPrepare">The <see cref="IQueryRequest" /> containing a N1QL statement to be prepared.</param>
 /// <param name="cancellationToken">Token which can cancel the query.</param>
 /// <returns>
 /// A <see cref="IQueryResult{T}" /> containing  the <see cref="QueryPlan" /> representing the reusable
 /// and cachable execution plan for the statement.
 /// </returns>
 /// <remarks>
 /// Most parameters in the IQueryRequest will be ignored, appart from the Statement and the BaseUri.
 /// </remarks>
 public async Task<IQueryResult<QueryPlan>> PrepareAsync(IQueryRequest toPrepare, CancellationToken cancellationToken)
 {
     var statement = toPrepare.GetOriginalStatement();
     if (!statement.ToUpper().StartsWith("PREPARE "))
     {
         statement = string.Concat("PREPARE ", statement);
     }
     var query = new QueryRequest(statement);
     query.BaseUri(toPrepare.GetBaseUri());
     return await ExecuteQueryAsync<QueryPlan>(query, cancellationToken).ContinueOnAnyContext();
 }
コード例 #7
0
        public QueryTimer(IQueryRequest queryRequest, ITimingStore store, bool enableQueryTiming)
        {
            Store = store;
            if (!store.Enabled || !enableQueryTiming) return;

            if (queryRequest == null)
            {
                throw new ArgumentException(QueryMustBeProvided);
            }

            if (string.IsNullOrEmpty(queryRequest.GetOriginalStatement()))
            {
                throw new ArgumentException(QueryStatementMustBeProvided);
            }

            _statement = queryRequest.GetOriginalStatement();
            _enableQueryTiming = enableQueryTiming;
            ClusterElapsedTime = NotRecorded;
            _stopwatch = Stopwatch.StartNew();
        }
コード例 #8
0
        private async Task <IQueryResult <T> > RetryAsync <T>(IQueryRequest queryRequest, CancellationToken cancellationToken)
        {
            //mark as retried, remove from cache
            queryRequest.HasBeenRetried = true;
            _queryCache.TryRemove(queryRequest.GetOriginalStatement(), out QueryPlan _);

            //re-optimize asynchronously
            await PrepareStatementIfNotAdHocAsync(queryRequest, cancellationToken).ContinueOnAnyContext();

            //re-execute asynchronously
            return(await ExecuteQueryAsync <T>(queryRequest, cancellationToken).ContinueOnAnyContext());
        }
コード例 #9
0
        public QueryTimer(IQueryRequest queryRequest, ITimingStore store, bool enableQueryTiming)
        {
            if (!store.Enabled || !enableQueryTiming)
            {
                return;
            }

            if (queryRequest == null)
            {
                throw new ArgumentException(QueryMustBeProvided);
            }

            if (string.IsNullOrEmpty(queryRequest.GetOriginalStatement()))
            {
                throw new ArgumentException(QueryStatementMustBeProvided);
            }

            Store              = store;
            _contextId         = queryRequest.CurrentContextId;
            _statement         = queryRequest.GetOriginalStatement();
            ClusterElapsedTime = NotRecorded;
            _stopwatch         = Stopwatch.StartNew();
        }
コード例 #10
0
        private async Task <IQueryResult <T> > RetryAsync <T>(IQueryRequest queryRequest)
        {
            //mark as retried, remove from cache
            queryRequest.HasBeenRetried = true;
            QueryPlan dismissed;

            _queryCache.TryRemove(queryRequest.GetOriginalStatement(), out dismissed);

            //re-optimize asynchronously
            await PrepareStatementIfNotAdHocAsync(queryRequest);

            //re-execute asynchronously
            return(await ExecuteQueryAsync <T>(queryRequest));
        }
コード例 #11
0
        private IQueryResult<T> Retry<T>(IQueryRequest queryRequest)
        {
            //mark as retried, remove from cache
            string key = queryRequest.GetOriginalStatement();
            queryRequest.HasBeenRetried = true;
            QueryPlan dismissed;
            _queryCache.TryRemove(key, out dismissed);

            //re-optimize
            PrepareStatementIfNotAdHoc(queryRequest);

            //re-execute
            return ExecuteQuery<T>(queryRequest);
        }