示例#1
0
        private static FeedResponseContext MakeFirstContextForPaging(object key)
        {
            var context = new FeedResponseContext();

            PagingContext.Add(key, context);
            return(context);
        }
示例#2
0
        /// <summary>
        /// This will execute a DocumentDB query in the form of an IQueryable (Linq form) and return the results.
        ///
        /// It handles paging, continuation tokens, and retriable errors such as "too many requests" for you,
        /// while aggregating all query results in-memory before returning.
        /// </summary>
        /// <typeparam name="R"></typeparam>
        /// <param name="queryable"></param>
        /// <param name="queryExecutionHandler"></param>
        /// <param name="enumerationExceptionHandler"></param>
        /// <param name="feedResponseHandler"></param>
        /// <param name="maxRetries"></param>
        /// <param name="maxTime"></param>
        /// <param name="shouldRetry"></param>
        /// <returns></returns>
        public static async Task <IList <R> > ExecuteQueryWithContinuationAndRetry <R>(IQueryable <R> queryable, QueryExecutionHandler queryExecutionHandler, EnumerationExceptionHandler enumerationExceptionHandler, FeedResponseHandler feedResponseHandler, int maxRetries, TimeSpan maxTime, ShouldRetry shouldRetry)
        {
            IDocumentQuery <R> query = null;

            try
            {
                query = queryable.AsDocumentQuery();
            }
            catch (Exception e)
            {
                throw new ArgumentException(BadQueryableMessage, e);
            }

            var context = new FeedResponseContext();

            queryExecutionHandler(context, query.ToString());

            feedResponseHandler(context, FeedResponseType.BeforeEnumeration, null);

            var allResults = new List <R>();

            while (query.HasMoreResults)
            {
                FeedResponse <R> intermediateResponse = null;
                try
                {
                    intermediateResponse = await DocumentDbReliableExecution.ExecuteResultWithRetry(() =>
                                                                                                    query.ExecuteNextAsync <R>(),
                                                                                                    null,
                                                                                                    maxRetries,
                                                                                                    maxTime,
                                                                                                    shouldRetry);
                }
                catch (Exception ex)
                {
                    bool handled = enumerationExceptionHandler(context, ex);
                    if (!handled)
                    {
                        feedResponseHandler(context, FeedResponseType.EnumerationAborted, null);
                        throw;
                    }
                    else
                    {
                        break;
                    }
                }

                // lots of interesting info in intermediateResults such as RU usage, etc.
                List <R> intermediateResults = intermediateResponse.ToList();
                UpdateContext <R>(context, intermediateResponse, JsonConvert.SerializeObject(intermediateResults).Length, query.HasMoreResults);
                feedResponseHandler(context, FeedResponseType.PageReceived, new FeedResponseWrapper <R>(intermediateResponse));

                allResults.AddRange(intermediateResults);
            }

            feedResponseHandler(context, FeedResponseType.AfterEnumeration, null);

            return(allResults);
        }
示例#3
0
 private static void UpdateContext <R>(FeedResponseContext context, FeedResponse <R> response, int resultJsonLength, bool hasMoreResults)
 {
     context.TotalCount                   += response.Count;
     context.TotalRequestCharge           += response.RequestCharge;
     context.TotalResultsJsonStringLength += resultJsonLength;
     if (!hasMoreResults)
     {
         context.StopTiming();
     }
 }
示例#4
0
        /// <summary>
        /// This will execute a DocumentDB FeedResponse method and return the results.
        ///
        /// It handles paging, continuation tokens, and retriable errors such as "too many requests" for you,
        /// while streaming query results out in chunks via IEnumerable / yield.
        /// </summary>
        /// <typeparam name="R"></typeparam>
        /// <param name="feedTakingContinuation"></param>
        /// <param name="enumerationExceptionHandler"></param>
        /// <param name="feedResponseHandler"></param>
        /// <param name="maxRetries"></param>
        /// <param name="maxTime"></param>
        /// <param name="shouldRetry"></param>
        /// <returns></returns>
        public static IEnumerable <R> StreamFeedWithContinuationAndRetry <R>(Func <string, Task <FeedResponse <R> > > feedTakingContinuation, EnumerationExceptionHandler enumerationExceptionHandler, FeedResponseHandler feedResponseHandler, int maxRetries, TimeSpan maxTime, ShouldRetry shouldRetry)
        {
            var context = new FeedResponseContext();

            feedResponseHandler(context, FeedResponseType.BeforeEnumeration, null);

            FeedResponse <R> intermediateResponse = null;

            do
            {
                Task <FeedResponse <R> > t;
                try
                {
                    t = Task.Run(async() => await ExecuteResultWithRetry(() =>
                                                                         feedTakingContinuation(intermediateResponse?.ResponseContinuation),
                                                                         null,
                                                                         maxRetries,
                                                                         maxTime,
                                                                         shouldRetry));

                    t.Wait();
                }
                catch (Exception ex)
                {
                    // note: if an IQueryable is returned to OData, throwing an exception here will cause it to take down w3wp.exe

                    bool handled = enumerationExceptionHandler(null, ex);
                    if (!handled)
                    {
                        feedResponseHandler(context, FeedResponseType.EnumerationAborted, null);
                        throw;
                    }
                    else
                    {
                        break;
                    }
                }

                intermediateResponse = t.Result;

                // lots of interesting info in intermediateResults such as RU usage, etc.
                List <R> intermediateResults = intermediateResponse.ToList();
                UpdateContext <R>(context, intermediateResponse, JsonConvert.SerializeObject(intermediateResults).Length, !string.IsNullOrEmpty(intermediateResponse.ResponseContinuation));
                feedResponseHandler(context, FeedResponseType.PageReceived, new FeedResponseWrapper <R>(intermediateResponse));

                foreach (var result in intermediateResults)
                {
                    yield return(result);
                }
            } while (!string.IsNullOrEmpty(intermediateResponse.ResponseContinuation));

            feedResponseHandler(context, FeedResponseType.AfterEnumeration, null);
        }
示例#5
0
        /// <summary>
        /// This will execute a DocumentDB FeedResponse method return the results.
        ///
        /// It handles paging, continuation tokens, and retriable errors such as "too many requests" for you,
        /// while aggregating all query results in-memory before returning.
        /// </summary>
        /// <typeparam name="R"></typeparam>
        /// <param name="feedTakingContinuation"></param>
        /// <param name="enumerationExceptionHandler"></param>
        /// <param name="feedResponseHandler"></param>
        /// <param name="maxRetries"></param>
        /// <param name="maxTime"></param>
        /// <param name="shouldRetry"></param>
        /// <returns></returns>
        public static async Task <IList <R> > ExecuteFeedWithContinuationAndRetry <R>(Func <string, Task <FeedResponse <R> > > feedTakingContinuation, EnumerationExceptionHandler enumerationExceptionHandler, FeedResponseHandler feedResponseHandler, int maxRetries, TimeSpan maxTime, ShouldRetry shouldRetry)
        {
            var context = new FeedResponseContext();

            feedResponseHandler(context, FeedResponseType.BeforeEnumeration, null);

            var allResults = new List <R>();

            FeedResponse <R> intermediateResponse = null;

            do
            {
                try
                {
                    intermediateResponse = await DocumentDbReliableExecution.ExecuteResultWithRetry(() =>
                                                                                                    feedTakingContinuation(intermediateResponse?.ResponseContinuation),
                                                                                                    null,
                                                                                                    maxRetries,
                                                                                                    maxTime,
                                                                                                    shouldRetry);
                }
                catch (Exception ex)
                {
                    bool handled = enumerationExceptionHandler(null, ex);
                    if (!handled)
                    {
                        feedResponseHandler(context, FeedResponseType.EnumerationAborted, null);
                        throw;
                    }
                    else
                    {
                        break;
                    }
                }

                // lots of interesting info in intermediateResults such as RU usage, etc.
                List <R> intermediateResults = intermediateResponse.ToList();
                UpdateContext <R>(context, intermediateResponse, JsonConvert.SerializeObject(intermediateResults).Length, !string.IsNullOrEmpty(intermediateResponse.ResponseContinuation));
                feedResponseHandler(context, FeedResponseType.PageReceived, new FeedResponseWrapper <R>(intermediateResponse));

                allResults.AddRange(intermediateResults);
            } while (!string.IsNullOrEmpty(intermediateResponse.ResponseContinuation));

            feedResponseHandler(context, FeedResponseType.AfterEnumeration, null);

            return(allResults);
        }
示例#6
0
        /// <summary>
        /// This will execute a DocumentDB query in the form of an IQueryable (Linq form) and return the results.
        ///
        /// It handles paging, continuation tokens, and retriable errors such as "too many requests" for you,
        /// while streaming query results out in chunks via IEnumerable / yield.
        /// </summary>
        /// <typeparam name="R"></typeparam>
        /// <param name="queryable"></param>
        /// <param name="queryExecutionHandler"></param>
        /// <param name="enumerationExceptionHandler"></param>
        /// <param name="feedResponseHandler"></param>
        /// <param name="maxRetries"></param>
        /// <param name="maxTime"></param>
        /// <param name="shouldRetry"></param>
        /// <returns></returns>
        public static IEnumerable <R> StreamQueryWithContinuationAndRetry <R>(IQueryable <R> queryable, QueryExecutionHandler queryExecutionHandler, EnumerationExceptionHandler enumerationExceptionHandler, FeedResponseHandler feedResponseHandler, int maxRetries, TimeSpan maxTime, ShouldRetry shouldRetry)
        {
            IDocumentQuery <R> query = null;

            try
            {
                query = queryable.AsDocumentQuery();
            }
            catch (Exception e)
            {
                throw new ArgumentException(BadQueryableMessage, e);
            }

            var context = new FeedResponseContext();

            queryExecutionHandler(context, query.ToString());

            feedResponseHandler(context, FeedResponseType.BeforeEnumeration, null);

            while (query.HasMoreResults)
            {
                Task <FeedResponse <R> > t;
                try
                {
                    t = Task.Run(async() => await ExecuteResultWithRetry(() =>
                                                                         query.ExecuteNextAsync <R>(),
                                                                         null,
                                                                         maxRetries,
                                                                         maxTime,
                                                                         shouldRetry));

                    t.Wait();
                }
                catch (Exception ex)
                {
                    // note: if an IQueryable is returned to OData, throwing an exception here will cause it to take down w3wp.exe

                    bool handled = enumerationExceptionHandler(context, ex);
                    if (!handled)
                    {
                        feedResponseHandler(context, FeedResponseType.EnumerationAborted, null);
                        throw;
                    }
                    else
                    {
                        break;
                    }
                }

                var intermediateResponse = t.Result;

                // lots of interesting info in intermediateResults such as RU usage, etc.
                List <R> intermediateResults = intermediateResponse.ToList();
                UpdateContext <R>(context, intermediateResponse, JsonConvert.SerializeObject(intermediateResults).Length, query.HasMoreResults);
                feedResponseHandler(context, FeedResponseType.PageReceived, new FeedResponseWrapper <R>(intermediateResponse));

                foreach (var result in intermediateResults)
                {
                    yield return(result);
                }
            }

            feedResponseHandler(context, FeedResponseType.AfterEnumeration, null);
        }