public static async Task <TakeDocumentQueryExecutionComponent> CreateLimitDocumentQueryExecutionComponentAsync(
            int limitCount,
            string continuationToken,
            Func <string, Task <IDocumentQueryExecutionComponent> > createSourceCallback)
        {
            LimitContinuationToken limitContinuationToken;

            if (continuationToken != null)
            {
                limitContinuationToken = LimitContinuationToken.Parse(continuationToken);
            }
            else
            {
                limitContinuationToken = new LimitContinuationToken(limitCount, null);
            }

            if (limitContinuationToken.Limit > limitCount)
            {
                throw new BadRequestException($"limit count in continuation token: {limitContinuationToken.Limit} can not be greater than the limit count in the query: {limitCount}.");
            }

            return(new TakeDocumentQueryExecutionComponent(
                       await createSourceCallback(limitContinuationToken.SourceToken),
                       limitContinuationToken.Limit,
                       TakeEnum.Limit));
        }
            public static async Task <TryCatch <IDocumentQueryExecutionComponent> > TryCreateLimitDocumentQueryExecutionComponentAsync(
                int limitCount,
                CosmosElement requestContinuationToken,
                Func <CosmosElement, Task <TryCatch <IDocumentQueryExecutionComponent> > > tryCreateSourceAsync)
            {
                if (limitCount < 0)
                {
                    throw new ArgumentException($"{nameof(limitCount)}: {limitCount} must be a non negative number.");
                }

                if (tryCreateSourceAsync == null)
                {
                    throw new ArgumentNullException(nameof(tryCreateSourceAsync));
                }

                LimitContinuationToken limitContinuationToken;

                if (requestContinuationToken != null)
                {
                    if (!LimitContinuationToken.TryParse(requestContinuationToken.ToString(), out limitContinuationToken))
                    {
                        return(TryCatch <IDocumentQueryExecutionComponent> .FromException(
                                   new MalformedContinuationTokenException($"Malformed {nameof(LimitContinuationToken)}: {requestContinuationToken}.")));
                    }
                }
                else
                {
                    limitContinuationToken = new LimitContinuationToken(limitCount, null);
                }

                if (limitContinuationToken.Limit > limitCount)
                {
                    return(TryCatch <IDocumentQueryExecutionComponent> .FromException(
                               new MalformedContinuationTokenException($"{nameof(LimitContinuationToken.Limit)} in {nameof(LimitContinuationToken)}: {requestContinuationToken}: {limitContinuationToken.Limit} can not be greater than the limit count in the query: {limitCount}.")));
                }

                CosmosElement sourceToken;

                if (limitContinuationToken.SourceToken != null)
                {
                    if (!CosmosElement.TryParse(limitContinuationToken.SourceToken, out sourceToken))
                    {
                        return(TryCatch <IDocumentQueryExecutionComponent> .FromException(
                                   new MalformedContinuationTokenException($"Malformed {nameof(LimitContinuationToken)}: {requestContinuationToken}.")));
                    }
                }
                else
                {
                    sourceToken = null;
                }

                return((await tryCreateSourceAsync(sourceToken))
                       .Try <IDocumentQueryExecutionComponent>((source) => new ClientTakeDocumentQueryExecutionComponent(
                                                                   source,
                                                                   limitContinuationToken.Limit,
                                                                   TakeEnum.Limit)));
            }
        public override async Task <QueryResponseCore> DrainAsync(int maxElements, CancellationToken token)
        {
            token.ThrowIfCancellationRequested();
            QueryResponseCore results = await base.DrainAsync(maxElements, token);

            if (!results.IsSuccess)
            {
                return(results);
            }

            List <CosmosElement> takedDocuments = results.CosmosElements.Take(this.takeCount).ToList();

            this.takeCount -= takedDocuments.Count;
            string updatedContinuationToken = null;

            if (results.DisallowContinuationTokenMessage == null)
            {
                if (!this.IsDone)
                {
                    string sourceContinuation = results.ContinuationToken;
                    TakeContinuationToken takeContinuationToken;
                    switch (this.takeEnum)
                    {
                    case TakeEnum.Limit:
                        takeContinuationToken = new LimitContinuationToken(
                            this.takeCount,
                            sourceContinuation);
                        break;

                    case TakeEnum.Top:
                        takeContinuationToken = new TopContinuationToken(
                            this.takeCount,
                            sourceContinuation);
                        break;

                    default:
                        throw new ArgumentException($"Unknown {nameof(TakeEnum)}: {this.takeEnum}");
                    }

                    updatedContinuationToken = takeContinuationToken.ToString();
                }
            }

            return(QueryResponseCore.CreateSuccess(
                       result: takedDocuments,
                       continuationToken: updatedContinuationToken,
                       disallowContinuationTokenMessage: results.DisallowContinuationTokenMessage,
                       activityId: results.ActivityId,
                       requestCharge: results.RequestCharge,
                       queryMetricsText: results.QueryMetricsText,
                       queryMetrics: results.QueryMetrics,
                       requestStatistics: results.RequestStatistics,
                       responseLengthBytes: results.ResponseLengthBytes));
        }
        public override async Task <FeedResponse <CosmosElement> > DrainAsync(int maxElements, CancellationToken token)
        {
            FeedResponse <CosmosElement> results = await base.DrainAsync(maxElements, token);

            List <CosmosElement> takedDocuments = results.Take(this.takeCount).ToList();

            results = new FeedResponse <CosmosElement>(
                takedDocuments,
                takedDocuments.Count,
                results.Headers,
                results.UseETagAsContinuation,
                results.QueryMetrics,
                results.RequestStatistics,
                results.DisallowContinuationTokenMessage,
                results.ResponseLengthBytes);

            this.takeCount -= takedDocuments.Count;

            if (results.DisallowContinuationTokenMessage == null)
            {
                if (!this.IsDone)
                {
                    string sourceContinuation = results.ResponseContinuation;
                    TakeContinuationToken takeContinuationToken;
                    switch (this.takeEnum)
                    {
                    case TakeEnum.Limit:
                        takeContinuationToken = new LimitContinuationToken(
                            this.takeCount,
                            sourceContinuation);
                        break;

                    case TakeEnum.Top:
                        takeContinuationToken = new TopContinuationToken(
                            this.takeCount,
                            sourceContinuation);
                        break;

                    default:
                        throw new ArgumentException($"Unknown {nameof(TakeEnum)}: {takeEnum}");
                    }

                    results.ResponseContinuation = takeContinuationToken.ToString();
                }
                else
                {
                    results.ResponseContinuation = null;
                }
            }

            return(results);
        }
        public override async Task <QueryResponse> DrainAsync(int maxElements, CancellationToken token)
        {
            token.ThrowIfCancellationRequested();
            QueryResponse results = await base.DrainAsync(maxElements, token);

            if (!results.IsSuccessStatusCode)
            {
                return(results);
            }

            List <CosmosElement> takedDocuments = results.CosmosElements.Take(this.takeCount).ToList();

            this.takeCount -= takedDocuments.Count;
            string updatedContinuationToken = null;

            if (results.QueryHeaders.DisallowContinuationTokenMessage == null)
            {
                if (!this.IsDone)
                {
                    string sourceContinuation = results.Headers.ContinuationToken;
                    TakeContinuationToken takeContinuationToken;
                    switch (this.takeEnum)
                    {
                    case TakeEnum.Limit:
                        takeContinuationToken = new LimitContinuationToken(
                            this.takeCount,
                            sourceContinuation);
                        break;

                    case TakeEnum.Top:
                        takeContinuationToken = new TopContinuationToken(
                            this.takeCount,
                            sourceContinuation);
                        break;

                    default:
                        throw new ArgumentException($"Unknown {nameof(TakeEnum)}: {this.takeEnum}");
                    }

                    updatedContinuationToken = takeContinuationToken.ToString();
                }
            }

            return(QueryResponse.CreateSuccess(
                       takedDocuments,
                       takedDocuments.Count,
                       results.ResponseLengthBytes,
                       results.QueryHeaders.CloneKnownProperties(updatedContinuationToken, results.QueryHeaders.DisallowContinuationTokenMessage),
                       results.queryMetrics));
        }
Example #6
0
            public override async Task <QueryResponseCore> DrainAsync(int maxElements, CancellationToken token)
            {
                token.ThrowIfCancellationRequested();
                QueryResponseCore sourcePage = await base.DrainAsync(maxElements, token);

                if (!sourcePage.IsSuccess)
                {
                    return(sourcePage);
                }

                List <CosmosElement> takedDocuments = sourcePage.CosmosElements.Take(this.takeCount).ToList();

                this.takeCount -= takedDocuments.Count;

                string updatedContinuationToken;

                if (!this.IsDone && (sourcePage.DisallowContinuationTokenMessage == null))
                {
                    switch (this.takeEnum)
                    {
                    case TakeEnum.Limit:
                        updatedContinuationToken = new LimitContinuationToken(
                            limit: this.takeCount,
                            sourceToken: sourcePage.ContinuationToken).ToString();
                        break;

                    case TakeEnum.Top:
                        updatedContinuationToken = new TopContinuationToken(
                            top: this.takeCount,
                            sourceToken: sourcePage.ContinuationToken).ToString();
                        break;

                    default:
                        throw new ArgumentOutOfRangeException($"Unknown {nameof(TakeEnum)}: {this.takeEnum}.");
                    }
                }
                else
                {
                    updatedContinuationToken = null;
                }

                return(QueryResponseCore.CreateSuccess(
                           result: takedDocuments,
                           continuationToken: updatedContinuationToken,
                           disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage,
                           activityId: sourcePage.ActivityId,
                           requestCharge: sourcePage.RequestCharge,
                           diagnostics: sourcePage.Diagnostics,
                           responseLengthBytes: sourcePage.ResponseLengthBytes));
            }
                /// <summary>
                /// Tries to parse out the LimitContinuationToken.
                /// </summary>
                /// <param name="value">The value to parse from.</param>
                /// <param name="limitContinuationToken">The result of parsing out the token.</param>
                /// <returns>Whether or not the LimitContinuationToken was successfully parsed out.</returns>
                public static bool TryParse(string value, out LimitContinuationToken limitContinuationToken)
                {
                    limitContinuationToken = default;
                    if (string.IsNullOrWhiteSpace(value))
                    {
                        return(false);
                    }

                    try
                    {
                        limitContinuationToken = JsonConvert.DeserializeObject <LimitContinuationToken>(value);
                        return(true);
                    }
                    catch (JsonException)
                    {
                        return(false);
                    }
                }
        public override bool TryGetContinuationToken(out string state)
        {
            if (!this.IsDone)
            {
                if (this.Source.TryGetContinuationToken(out string sourceState))
                {
                    TakeContinuationToken takeContinuationToken;
                    switch (this.takeEnum)
                    {
                    case TakeEnum.Limit:
                        takeContinuationToken = new LimitContinuationToken(
                            this.takeCount,
                            sourceState);
                        break;

                    case TakeEnum.Top:
                        takeContinuationToken = new TopContinuationToken(
                            this.takeCount,
                            sourceState);
                        break;

                    default:
                        throw new ArgumentException($"Unknown {nameof(TakeEnum)}: {this.takeEnum}");
                    }

                    state = takeContinuationToken.ToString();
                    return(true);
                }
                else
                {
                    state = default(string);
                    return(false);
                }
            }
            else
            {
                state = default(string);
                return(true);
            }
        }
            /// <summary>
            /// Tries to parse out the LimitContinuationToken.
            /// </summary>
            /// <param name="value">The value to parse from.</param>
            /// <param name="LimitContinuationToken">The result of parsing out the token.</param>
            /// <returns>Whether or not the LimitContinuationToken was successfully parsed out.</returns>
            public static bool TryParse(string value, out LimitContinuationToken LimitContinuationToken)
            {
                LimitContinuationToken = default(LimitContinuationToken);
                if (string.IsNullOrWhiteSpace(value))
                {
                    return(false);
                }

                try
                {
                    LimitContinuationToken = JsonConvert.DeserializeObject <LimitContinuationToken>(value);
                    return(true);
                }
                catch (JsonException ex)
                {
                    DefaultTrace.TraceWarning(string.Format(
                                                  CultureInfo.InvariantCulture,
                                                  "{0} Invalid continuation token {1} for limit~Component, exception: {2}",
                                                  DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture),
                                                  value,
                                                  ex.Message));
                    return(false);
                }
            }
            public static TryCatch <IQueryPipelineStage> MonadicCreateLimitStage(
                int limitCount,
                CosmosElement requestContinuationToken,
                CancellationToken cancellationToken,
                MonadicCreatePipelineStage monadicCreatePipelineStage)
            {
                if (limitCount < 0)
                {
                    throw new ArgumentException($"{nameof(limitCount)}: {limitCount} must be a non negative number.");
                }

                if (monadicCreatePipelineStage == null)
                {
                    throw new ArgumentNullException(nameof(monadicCreatePipelineStage));
                }

                LimitContinuationToken limitContinuationToken;

                if (requestContinuationToken != null)
                {
                    if (!LimitContinuationToken.TryParse(requestContinuationToken.ToString(), out limitContinuationToken))
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       $"Malformed {nameof(LimitContinuationToken)}: {requestContinuationToken}.")));
                    }
                }
                else
                {
                    limitContinuationToken = new LimitContinuationToken(limitCount, null);
                }

                if (limitContinuationToken.Limit > limitCount)
                {
                    return(TryCatch <IQueryPipelineStage> .FromException(
                               new MalformedContinuationTokenException(
                                   $"{nameof(LimitContinuationToken.Limit)} in {nameof(LimitContinuationToken)}: {requestContinuationToken}: {limitContinuationToken.Limit} can not be greater than the limit count in the query: {limitCount}.")));
                }

                CosmosElement sourceToken;

                if (limitContinuationToken.SourceToken != null)
                {
                    TryCatch <CosmosElement> tryParse = CosmosElement.Monadic.Parse(limitContinuationToken.SourceToken);
                    if (tryParse.Failed)
                    {
                        return(TryCatch <IQueryPipelineStage> .FromException(
                                   new MalformedContinuationTokenException(
                                       message : $"Malformed {nameof(LimitContinuationToken)}: {requestContinuationToken}.",
                                       innerException : tryParse.Exception)));
                    }

                    sourceToken = tryParse.Result;
                }
                else
                {
                    sourceToken = null;
                }

                TryCatch <IQueryPipelineStage> tryCreateSource = monadicCreatePipelineStage(sourceToken, cancellationToken);

                if (tryCreateSource.Failed)
                {
                    return(tryCreateSource);
                }

                IQueryPipelineStage stage = new ClientTakeQueryPipelineStage(
                    tryCreateSource.Result,
                    cancellationToken,
                    limitContinuationToken.Limit,
                    TakeEnum.Limit);

                return(TryCatch <IQueryPipelineStage> .FromResult(stage));
            }