Beispiel #1
0
        internal static async Task <List <T> > QueryWithContinuationTokensAsync <T>(
            Container container,
            string query,
            QueryRequestOptions queryRequestOptions = null)
        {
            if (queryRequestOptions == null)
            {
                queryRequestOptions = new QueryRequestOptions();
            }

            List <T> resultsFromContinuationToken = new List <T>();
            string   continuationToken            = null;

            do
            {
                FeedIterator <T> itemQuery = container.GetItemQueryIterator <T>(
                    queryText: query,
                    requestOptions: queryRequestOptions,
                    continuationToken: continuationToken);

                try
                {
                    while (true)
                    {
                        try
                        {
                            FeedResponse <T> cosmosQueryResponse = await itemQuery.ReadNextAsync();

                            if (queryRequestOptions.MaxItemCount.HasValue)
                            {
                                Assert.IsTrue(
                                    cosmosQueryResponse.Count <= queryRequestOptions.MaxItemCount.Value,
                                    "Max Item Count is not being honored");
                            }

                            resultsFromContinuationToken.AddRange(cosmosQueryResponse);
                            continuationToken = cosmosQueryResponse.ContinuationToken;
                            break;
                        }
                        catch (CosmosException cosmosException) when(cosmosException.StatusCode == (HttpStatusCode)429)
                        {
                            itemQuery.Dispose();
                            itemQuery = container.GetItemQueryIterator <T>(
                                queryText: query,
                                requestOptions: queryRequestOptions,
                                continuationToken: continuationToken);
                        }
                    }
                }
                finally
                {
                    itemQuery.Dispose();
                }
            } while (continuationToken != null);

            return(resultsFromContinuationToken);
        }
Beispiel #2
0
 protected virtual void Dispose(bool disposing)
 {
     if (disposing)
     {
         _feedIterator?.Dispose();
     }
 }
Beispiel #3
0
        private static async Task <List <Application> > GetMatchesAsync(FeedIterator <Application> query)
        {
            List <Application> applications = new List <Application>();

            while (query.HasMoreResults)
            {
                FeedResponse <Application> response = await query.ReadNextAsync();

                applications.AddRange(response);
            }

            query.Dispose();

            PostProcess(applications);

            return(applications);
        }
        /// <summary>
        /// Executes the query and does paging using continuations.
        /// </summary>
        private async static Task ExecuteQueryWithContinuationAndGatherResultsAsync(CTLConfig config,
                                                                                    CosmosClient cosmosClient,
                                                                                    ILogger logger,
                                                                                    IMetrics metrics,
                                                                                    string loggingContextIdentifier,
                                                                                    CancellationToken cancellationToken,
                                                                                    string queryText,
                                                                                    string queryName,
                                                                                    long expectedResults,
                                                                                    SemaphoreSlim concurrencyControlSemaphore)
        {
            Stopwatch stopWatch = Stopwatch.StartNew();

            GaugeOptions documentGauge = new GaugeOptions
            {
                Name            = $"#{queryName} Query with CT received documents",
                MeasurementUnit = Unit.Items,
                Context         = loggingContextIdentifier
            };

            Container container = cosmosClient.GetContainer(config.Database, config.Collection);

            while (stopWatch.Elapsed <= config.RunningTimeDurationAsTimespan &&
                   !cancellationToken.IsCancellationRequested)
            {
                // To really debug what happened on the query, having a list of all continuations would be useful.
                List <string> allContinuations = new List <string>();
                long          documentTotal    = 0;
                string        continuation;
                await concurrencyControlSemaphore.WaitAsync();

                FeedIterator <Dictionary <string, string> > query = container.GetItemQueryIterator <Dictionary <string, string> >(queryText);
                try
                {
                    while (query.HasMoreResults)
                    {
                        FeedResponse <Dictionary <string, string> > response = await query.ReadNextAsync();

                        documentTotal += response.Count;
                        continuation   = response.ContinuationToken;
                        allContinuations.Add(continuation);
                        if (continuation != null)
                        {
                            // Use continuation to paginate on the query instead of draining just the initial query
                            // This validates that we can indeed move forward with the continuation
                            query.Dispose();
                            query = container.GetItemQueryIterator <Dictionary <string, string> >(queryText, continuation);
                        }
                    }

                    query.Dispose();

                    metrics.Measure.Gauge.SetValue(documentGauge, documentTotal);

                    if (expectedResults > 0 && expectedResults != documentTotal)
                    {
                        StringBuilder errorDetail = new StringBuilder();
                        errorDetail.AppendLine($"{queryName} Query with CT expected to read {expectedResults} but got {documentTotal}");
                        foreach (string c in allContinuations)
                        {
                            errorDetail.AppendLine($"Continuation: {c}");
                        }

                        logger.LogError(errorDetail.ToString());
                    }
                }
                catch (CosmosException ce) when(ce.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
                {
                    //Logging 429s is not relevant
                }
                catch (Exception ex)
                {
                    metrics.Measure.Gauge.SetValue(documentGauge, documentTotal);

                    StringBuilder errorDetail = new StringBuilder();
                    errorDetail.AppendLine($"{queryName} Query with CT failure while looping through query.");
                    foreach (string c in allContinuations)
                    {
                        errorDetail.AppendLine($"Continuation: {c}");
                    }

                    logger.LogError(ex, errorDetail.ToString());
                }
                finally
                {
                    concurrencyControlSemaphore.Release();
                }
            }

            stopWatch.Stop();
        }
Beispiel #5
0
        internal static async Task <List <T> > QueryWithoutContinuationTokensAsync <T>(
            Container container,
            string query,
            QueryRequestOptions queryRequestOptions = null)
        {
            if (queryRequestOptions == null)
            {
                queryRequestOptions = new QueryRequestOptions();
            }

            List <T>         results   = new List <T>();
            FeedIterator <T> itemQuery = container.GetItemQueryIterator <T>(
                queryText: query,
                requestOptions: queryRequestOptions);

            try
            {
                string continuationTokenForRetries = null;
                while (itemQuery.HasMoreResults)
                {
                    try
                    {
                        FeedResponse <T> page = await itemQuery.ReadNextAsync();

                        results.AddRange(page);

                        if (queryRequestOptions.MaxItemCount.HasValue)
                        {
                            Assert.IsTrue(
                                page.Count <= queryRequestOptions.MaxItemCount.Value,
                                "Max Item Count is not being honored");
                        }

                        try
                        {
                            continuationTokenForRetries = page.ContinuationToken;
                        }
                        catch (Exception)
                        {
                            // Grabbing a continuation token is not supported on all queries.
                        }
                    }
                    catch (CosmosException cosmosException) when(cosmosException.StatusCode == (HttpStatusCode)429)
                    {
                        itemQuery.Dispose();
                        itemQuery = container.GetItemQueryIterator <T>(
                            queryText: query,
                            requestOptions: queryRequestOptions,
                            continuationToken: continuationTokenForRetries);

                        if (continuationTokenForRetries == null)
                        {
                            // The query failed and we don't have a save point, so just restart the whole thing.
                            results = new List <T>();
                        }
                    }
                }
            }
            finally
            {
                itemQuery.Dispose();
            }

            return(results);
        }