public async Task TestOperationCanceledExceptionAsync()
        {
            int    seed = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
            Random rand = new Random(seed);
            IDocumentClientRetryPolicy retryPolicy = new MockRetryPolicy(rand);
            ComparableTaskScheduler    scheduler   = new ComparableTaskScheduler(1);

            DocumentProducer <int> producer = new DocumentProducer <int>(
                scheduler,
                (continuation, pageSize) => null,
                new PartitionKeyRange {
                Id = "test", MinInclusive = "", MaxExclusive = "ff"
            },
                p => 0,
                (request, token) =>
            {
                scheduler.Stop();
                throw new Exception();
            },
                () => retryPolicy,
                (produer, size, ru, queryMetrics, token, length) => { },
                Guid.NewGuid()
                )
            {
                PageSize = 1000
            };

            await producer.MoveNextAsync(new CancellationTokenSource().Token);
        }
Example #2
0
        public override async Task <FeedResponse <object> > DrainAsync(int maxElements, CancellationToken token)
        {
            List <object> result      = new List <object>();
            List <Uri>    replicaUris = new List <Uri>();
            ClientSideRequestStatistics requestStats = new ClientSideRequestStatistics();

            while (!this.IsDone)
            {
                DocumentProducer <object> currentDocumentProducer = base.DocumentProducers[this.currentDocumentProducerIndex];

                if (currentDocumentProducer.IsAtContinuationBoundary)
                {
                    if (maxElements - result.Count < currentDocumentProducer.ItemsTillNextContinuationBoundary)
                    {
                        break;
                    }

                    base.CurrentContinuationTokens[currentDocumentProducer] = currentDocumentProducer.ResponseContinuation;

                    result.Add(currentDocumentProducer.Current);

                    if (currentDocumentProducer.RequestStatistics != null)
                    {
                        replicaUris.AddRange(currentDocumentProducer.RequestStatistics.ContactedReplicas);
                    }

                    while (currentDocumentProducer.ItemsTillNextContinuationBoundary > 1)
                    {
                        bool hasMoreResults = await currentDocumentProducer.MoveNextAsync(token);

                        Debug.Assert(hasMoreResults, "Expect hasMoreResults be true.");
                        result.Add(currentDocumentProducer.Current);
                    }
                }

                if (!await this.TryMoveNextProducerAsync(currentDocumentProducer, token))
                {
                    ++this.currentDocumentProducerIndex;

                    if (this.currentDocumentProducerIndex < base.DocumentProducers.Count &&
                        !base.CurrentContinuationTokens.ContainsKey(base.DocumentProducers[this.currentDocumentProducerIndex]))
                    {
                        base.CurrentContinuationTokens[base.DocumentProducers[this.currentDocumentProducerIndex]] = null;
                    }

                    continue;
                }

                if (maxElements >= int.MaxValue && result.Count > this.ActualMaxBufferedItemCount)
                {
                    break;
                }
            }

            this.ReduceTotalBufferedItems(result.Count);
            requestStats.ContactedReplicas.AddRange(replicaUris);

            return(new FeedResponse <object>(result, result.Count, this.ResponseHeaders, requestStats, this.GetAndResetResponseLengthBytes()));
        }
Example #3
0
        protected async Task <bool> TryMoveNextProducerAsync(
            DocumentProducer <T> producer,
            Func <DocumentProducer <T>, Task <DocumentProducer <T> > > producerRepairCallback,
            CancellationToken cancellationToken)
        {
            bool movedNext = false;
            DocumentProducer <T> currentProducer = producer;

            while (true)
            {
                bool needRefreshedPartitionKeyRangeCache = false;
                try
                {
                    movedNext = await currentProducer.MoveNextAsync(cancellationToken);
                }
                catch (DocumentClientException ex)
                {
                    if (!(needRefreshedPartitionKeyRangeCache = base.NeedPartitionKeyRangeCacheRefresh(ex)))
                    {
                        throw;
                    }
                }

                if (needRefreshedPartitionKeyRangeCache)
                {
                    currentProducer = await producerRepairCallback(currentProducer);
                }
                else
                {
                    break;
                }
            }

            if (!movedNext)
            {
                this.CurrentContinuationTokens.Remove(currentProducer);
            }

            return(movedNext);
        }
Example #4
0
        private async Task FilterAsync(
            DocumentProducer <OrderByQueryResult> producer,
            SortOrder[] sortOrders,
            OrderByContinuationToken continuationToken,
            CancellationToken cancellationToken)
        {
            ResourceId continuationRid;

            if (!ResourceId.TryParse(continuationToken.Rid, out continuationRid))
            {
                DefaultTrace.TraceWarning(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "{0}, CorrelatedActivityId: {1}, ActivityId: {2} | Invalid Rid in the continuation token {3} for OrderBy~Context.",
                        DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture),
                        this.CorrelatedActivityId,
                        this.ActivityId,
                        continuationToken.CompositeToken.Token));
                throw new BadRequestException(RMResources.InvalidContinuationToken);
            }

            Dictionary <string, ResourceId> resourceIds = new Dictionary <string, ResourceId>();
            int  itemToSkip = continuationToken.SkipCount;
            bool continuationRidVerified = false;

            while (true)
            {
                OrderByQueryResult orderByResult = (OrderByQueryResult)producer.Current;

                int cmp = 0;
                for (int i = 0; i < sortOrders.Length; ++i)
                {
                    cmp = ItemComparer.Instance.Compare(
                        continuationToken.OrderByItems[i].GetItem(),
                        orderByResult.OrderByItems[i].GetItem());

                    if (cmp != 0)
                    {
                        cmp = sortOrders[i] != SortOrder.Descending ? cmp : -cmp;
                        break;
                    }
                }

                if (cmp < 0)
                {
                    break;
                }

                if (cmp == 0)
                {
                    ResourceId rid;
                    if (!resourceIds.TryGetValue(orderByResult.Rid, out rid))
                    {
                        if (!ResourceId.TryParse(orderByResult.Rid, out rid))
                        {
                            DefaultTrace.TraceWarning(
                                string.Format(
                                    CultureInfo.InvariantCulture,
                                    "{0}, CorrelatedActivityId: {1}, ActivityId: {2} | Invalid Rid in the continuation token {3} for OrderBy~Context.",
                                    DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture),
                                    this.CorrelatedActivityId,
                                    this.ActivityId,
                                    continuationToken.CompositeToken.Token));
                            throw new BadRequestException(RMResources.InvalidContinuationToken);
                        }

                        resourceIds.Add(orderByResult.Rid, rid);
                    }

                    if (!continuationRidVerified)
                    {
                        if (continuationRid.Database != rid.Database || continuationRid.DocumentCollection != rid.DocumentCollection)
                        {
                            DefaultTrace.TraceWarning(
                                string.Format(
                                    CultureInfo.InvariantCulture,
                                    "{0}, CorrelatedActivityId: {1}, ActivityId: {2} | Invalid Rid in the continuation token {3} for OrderBy~Context.",
                                    DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture),
                                    this.CorrelatedActivityId,
                                    this.ActivityId,
                                    continuationToken.CompositeToken.Token));
                            throw new BadRequestException(RMResources.InvalidContinuationToken);
                        }

                        continuationRidVerified = true;
                    }

                    cmp = continuationRid.Document.CompareTo(rid.Document);
                    if (sortOrders[sortOrders.Length - 1] == SortOrder.Descending)
                    {
                        cmp = -cmp;
                    }

                    if (cmp < 0 || (cmp == 0 && itemToSkip-- <= 0))
                    {
                        break;
                    }
                }


                if (!await producer.MoveNextAsync(cancellationToken))
                {
                    break;
                }
            }
        }
        public async Task ConcurrentMoveNextTryScheduleTestAsync()
        {
            int    seed     = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
            Random rand     = new Random(seed);
            int    maxValue = 100;
            int    trials   = 1000;
            int    maxTicks = 100;

            IEnumerable <int>          expectedValues = Enumerable.Range(1, maxValue);
            IDocumentClientRetryPolicy retryPolicy    = new MockRetryPolicy(rand);
            ComparableTaskScheduler    scheduler      = new ComparableTaskScheduler(1);

            for (int trial = 0; trial < trials; ++trial)
            {
                DocumentProducer <int> producer = new DocumentProducer <int>(
                    scheduler,
                    (continuation, pageSize) => DocumentServiceRequest.Create(
                        OperationType.Query,
                        "/dbs/db/colls/coll",
                        ResourceType.Document,
                        new MemoryStream(Encoding.UTF8.GetBytes(continuation)),
                        AuthorizationTokenType.PrimaryMasterKey,
                        new StringKeyValueCollection
                {
                    { HttpConstants.HttpHeaders.Continuation, continuation }
                }),
                    new PartitionKeyRange {
                    Id = "test", MinInclusive = "", MaxExclusive = "ff"
                },
                    p => 0,
                    (request, token) =>
                {
                    if (rand.Next(4) == 0)
                    {
                        throw new Exception();
                    }

                    if (rand.Next(10) == 0)
                    {
                        return(Task.FromResult(new FeedResponse <int>(new int[] { }, 0, request.Headers)));
                    }

                    using (StreamReader reader = new StreamReader(request.Body))
                    {
                        int value = int.Parse(reader.ReadToEnd()) + 1;
                        INameValueCollection headers = new StringKeyValueCollection
                        {
                            { HttpConstants.HttpHeaders.Continuation, value >= maxValue? null : value.ToString(CultureInfo.InvariantCulture) }
                        };
                        return(Task.FromResult(new FeedResponse <int>(new int[] { value }, 1, headers)));
                    }
                },
                    () => retryPolicy,
                    (produer, size, ru, queryMetrics, token, length) => { },
                    Guid.NewGuid(),
                    1000,
                    "0");

                Timer timer = new Timer(
                    (state) => producer.TryScheduleFetch(TimeSpan.FromTicks(rand.Next(maxTicks))),
                    null,
                    TimeSpan.FromTicks(rand.Next(maxTicks)),
                    TimeSpan.FromTicks(rand.Next(maxTicks)));

                List <int> actualValues             = new List <int>();
                CancellationTokenSource tokenSource = new CancellationTokenSource(5000);
                while (await producer.MoveNextAsync(tokenSource.Token))
                {
                    actualValues.Add(producer.Current);
                }

                Assert.AreEqual(
                    string.Join(", ", expectedValues),
                    string.Join(", ", actualValues),
                    string.Format(CultureInfo.InvariantCulture, "seed: {0}", seed));
            }
        }