private ChangeFeedIteratorCore( ContainerInternal container, ChangeFeedRequestOptions changeFeedRequestOptions) { if (changeFeedRequestOptions != null && changeFeedRequestOptions.MaxItemCount.HasValue && changeFeedRequestOptions.MaxItemCount.Value <= 0) { throw new ArgumentOutOfRangeException(nameof(changeFeedRequestOptions.MaxItemCount)); } this.container = container ?? throw new ArgumentNullException(nameof(container)); this.clientContext = container.ClientContext; this.changeFeedOptions = changeFeedRequestOptions ?? new ChangeFeedRequestOptions(); this.lazyContainerRid = new AsyncLazy <TryCatch <string> >(valueFactory: (innerCancellationToken) => { return(this.TryInitializeContainerRIdAsync(innerCancellationToken)); }); }
internal static async Task <T> ProcessResourceOperationAsync <T>( RequestInvokerHandler requestHandler, string resourceUri, ResourceType resourceType, OperationType operationType, RequestOptions requestOptions, ContainerInternal cosmosContainerCore, FeedRange feedRange, Stream streamPayload, Action <RequestMessage> requestEnricher, Func <ResponseMessage, T> responseCreator, CancellationToken cancellationToken) { if (requestHandler == null) { throw new ArgumentException(nameof(requestHandler)); } if (resourceUri == null) { throw new ArgumentNullException(nameof(resourceUri)); } if (responseCreator == null) { throw new ArgumentNullException(nameof(responseCreator)); } ResponseMessage response = await requestHandler.SendAsync( resourceUri, resourceType, operationType, requestOptions, cosmosContainerCore, feedRange, streamPayload, requestEnricher, null, NoOpTrace.Singleton, cancellationToken); return(responseCreator(response)); }
internal ChangeFeedProcessorBuilder( string processorName, ContainerInternal container, ChangeFeedProcessor changeFeedProcessor, Action <DocumentServiceLeaseStoreManager, ContainerInternal, string, ChangeFeedLeaseOptions, ChangeFeedProcessorOptions, ContainerInternal> applyBuilderConfiguration) { this.changeFeedLeaseOptions = new ChangeFeedLeaseOptions { LeasePrefix = processorName }; this.monitoredContainer = container; this.changeFeedProcessor = changeFeedProcessor; this.applyBuilderConfiguration = applyBuilderConfiguration; }
/// <summary> /// Sets the Cosmos Container to hold the leases state /// </summary> /// <param name="leaseContainer">Instance of a Cosmos Container to hold the leases.</param> /// <returns>The instance of <see cref="ChangeFeedProcessorBuilder"/> to use.</returns> public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer) { if (leaseContainer == null) { throw new ArgumentNullException(nameof(leaseContainer)); } if (this.leaseContainer != null) { throw new InvalidOperationException("The builder already defined a lease container."); } if (this.LeaseStoreManager != null) { throw new InvalidOperationException("The builder already defined an in-memory lease container instance."); } this.leaseContainer = (ContainerInternal)leaseContainer; return(this); }
public static ChangeFeedIteratorCore Create( ContainerInternal container, FeedRangeInternal feedRangeInternal, string continuation, ChangeFeedRequestOptions changeFeedRequestOptions) { if (!string.IsNullOrEmpty(continuation)) { if (FeedRangeContinuation.TryParse(continuation, out FeedRangeContinuation feedRangeContinuation)) { return(new ChangeFeedIteratorCore(container, feedRangeContinuation, changeFeedRequestOptions)); } else { throw new ArgumentException(string.Format(ClientResources.FeedToken_UnknownFormat, continuation)); } } feedRangeInternal = feedRangeInternal ?? FeedRangeEPK.ForCompleteRange(); return(new ChangeFeedIteratorCore(container, feedRangeInternal, changeFeedRequestOptions)); }
public BatchAsyncContainerExecutor( ContainerInternal cosmosContainer, CosmosClientContext cosmosClientContext, int maxServerRequestOperationCount, int maxServerRequestBodyLength) { if (maxServerRequestOperationCount < 1) { throw new ArgumentOutOfRangeException(nameof(maxServerRequestOperationCount)); } if (maxServerRequestBodyLength < 1) { throw new ArgumentOutOfRangeException(nameof(maxServerRequestBodyLength)); } this.cosmosContainer = cosmosContainer ?? throw new ArgumentNullException(nameof(cosmosContainer)); this.cosmosClientContext = cosmosClientContext; this.maxServerRequestBodyLength = maxServerRequestBodyLength; this.maxServerRequestOperationCount = maxServerRequestOperationCount; this.timerWheel = TimerWheel.CreateTimerWheel(BatchAsyncContainerExecutor.TimerWheelResolution, BatchAsyncContainerExecutor.TimerWheelBucketCount); this.retryOptions = cosmosClientContext.ClientOptions.GetConnectionPolicy().RetryOptions; }
private async Task <ResponseMessage> ProcessItemStreamAsync( PartitionKey?partitionKey, string itemId, Stream streamPayload, OperationType operationType, ItemRequestOptions requestOptions, CosmosDiagnosticsContext diagnosticsContext, CancellationToken cancellationToken) { if (diagnosticsContext == null) { throw new ArgumentNullException(nameof(diagnosticsContext)); } if (requestOptions != null && requestOptions.IsEffectivePartitionKeyRouting) { partitionKey = null; } ContainerInternal.ValidatePartitionKey(partitionKey, requestOptions); string resourceUri = this.GetResourceUri(requestOptions, operationType, itemId); ResponseMessage responseMessage = await this.ClientContext.ProcessResourceOperationStreamAsync( resourceUri : resourceUri, resourceType : ResourceType.Document, operationType : operationType, requestOptions : requestOptions, cosmosContainerCore : this, partitionKey : partitionKey, itemId : itemId, streamPayload : streamPayload, requestEnricher : null, diagnosticsContext : diagnosticsContext, cancellationToken : cancellationToken); return(responseMessage); }
internal abstract BatchAsyncContainerExecutor GetExecutorForContainer( ContainerInternal container);
public FeedRangePartitionKeyRangeExtractor(ContainerInternal container) { this.container = container ?? throw new ArgumentNullException(nameof(container)); }
public override async Task <ContainerResponse> CreateContainerIfNotExistsAsync( ContainerProperties containerProperties, int?throughput = null, RequestOptions requestOptions = null, CancellationToken cancellationToken = default(CancellationToken)) { if (containerProperties == null) { throw new ArgumentNullException(nameof(containerProperties)); } this.ValidateContainerProperties(containerProperties); ContainerInternal container = (ContainerInternal)this.GetContainer(containerProperties.Id); ResponseMessage readResponse = await this.ProcessResourceOperationStreamAsync( null, OperationType.Read, container.LinkUri, ResourceType.Collection, requestOptions, cancellationToken); if (readResponse.StatusCode != HttpStatusCode.NotFound) { ContainerResponse retrivedContainerResponse = this.ClientContext.ResponseFactory.CreateContainerResponse( container, readResponse); if (!retrivedContainerResponse.Resource.PartitionKeyPath.Equals(containerProperties.PartitionKeyPath)) { throw new ArgumentException( string.Format( ClientResources.PartitionKeyPathConflict, containerProperties.PartitionKeyPath, containerProperties.Id, retrivedContainerResponse.Resource.PartitionKeyPath), nameof(containerProperties.PartitionKey)); } return(retrivedContainerResponse); } this.ValidateContainerProperties(containerProperties); ResponseMessage createResponse = await this.CreateContainerStreamAsync( containerProperties, throughput, requestOptions, cancellationToken); // Merge the previous message diagnostics createResponse.DiagnosticsContext.AddDiagnosticsInternal(readResponse.DiagnosticsContext); if (readResponse.StatusCode != HttpStatusCode.Conflict) { return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, createResponse)); } // This second Read is to handle the race condition when 2 or more threads have Read the database and only one succeeds with Create // so for the remaining ones we should do a Read instead of throwing Conflict exception ResponseMessage readResponseAfterCreate = await this.ProcessResourceOperationStreamAsync( null, OperationType.Read, container.LinkUri, ResourceType.Collection, requestOptions, cancellationToken); // Merge the previous message diagnostics createResponse.DiagnosticsContext.AddDiagnosticsInternal(readResponse.DiagnosticsContext); return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, readResponseAfterCreate)); }
public abstract Task <Documents.ShouldRetryResult> HandleSplitAsync( ContainerInternal containerCore, ResponseMessage responseMessage, CancellationToken cancellationToken);
internal static async Task <TransactionalBatchResponse> FromResponseMessageAsync( ResponseMessage responseMessage, ServerBatchRequest serverRequest, CosmosSerializerCore serializer, bool shouldPromoteOperationStatus, bool shouldPerformDecryption, CancellationToken cancellationToken) { using (responseMessage) { TransactionalBatchResponse response = null; if (responseMessage.Content != null) { Stream content = responseMessage.Content; // Shouldn't be the case practically, but handle it for safety. if (!responseMessage.Content.CanSeek) { content = new MemoryStream(); await responseMessage.Content.CopyToAsync(content); } if (content.ReadByte() == (int)HybridRowVersion.V1) { content.Position = 0; response = await TransactionalBatchResponse.PopulateFromContentAsync( content, responseMessage, serverRequest, serializer, shouldPromoteOperationStatus); if (response == null) { // Convert any payload read failures as InternalServerError response = new TransactionalBatchResponse( HttpStatusCode.InternalServerError, SubStatusCodes.Unknown, ClientResources.ServerResponseDeserializationFailure, responseMessage.Headers.RequestCharge, responseMessage.Headers.RetryAfter, responseMessage.Headers.ActivityId, responseMessage.DiagnosticsContext, serverRequest.Operations, serializer); } } } if (response == null) { response = new TransactionalBatchResponse( responseMessage.StatusCode, responseMessage.Headers.SubStatusCode, responseMessage.ErrorMessage, responseMessage.Headers.RequestCharge, responseMessage.Headers.RetryAfter, responseMessage.Headers.ActivityId, responseMessage.DiagnosticsContext, serverRequest.Operations, serializer); } if (response.results == null || response.results.Count != serverRequest.Operations.Count) { if (responseMessage.IsSuccessStatusCode) { // Server should be guaranteeing number of results equal to operations when // batch request is successful - so fail as InternalServerError if this is not the case. response = new TransactionalBatchResponse( HttpStatusCode.InternalServerError, SubStatusCodes.Unknown, ClientResources.InvalidServerResponse, responseMessage.Headers.RequestCharge, responseMessage.Headers.RetryAfter, responseMessage.Headers.ActivityId, responseMessage.DiagnosticsContext, serverRequest.Operations, serializer); } // When the overall response status code is TooManyRequests, propagate the RetryAfter into the individual operations. int retryAfterMilliseconds = 0; if ((int)responseMessage.StatusCode == (int)StatusCodes.TooManyRequests) { if (!responseMessage.Headers.TryGetValue(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, out string retryAfter) || retryAfter == null || !int.TryParse(retryAfter, out retryAfterMilliseconds)) { retryAfterMilliseconds = 0; } } response.CreateAndPopulateResults(serverRequest.Operations, retryAfterMilliseconds); } else if (shouldPerformDecryption) { for (int index = 0; index < serverRequest.Operations.Count; index++) { ContainerInternal containerCore = serverRequest.Operations[index].ContainerInternal; TransactionalBatchOperationResult result = response.results[index]; result.ResourceStream = await containerCore.ClientContext.DecryptItemAsync( result.ResourceStream, (DatabaseInternal)containerCore.Database, responseMessage.DiagnosticsContext, cancellationToken); } } return(response); } }