public async Task <ContainerResponse> CreateContainerIfNotExistsAsync( CosmosDiagnosticsContext diagnosticsContext, ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions, CancellationToken cancellationToken) { if (containerProperties == null) { throw new ArgumentNullException(nameof(containerProperties)); } this.ValidateContainerProperties(containerProperties); ContainerCore container = (ContainerCore)this.GetContainer(containerProperties.Id); using (ResponseMessage readResponse = await container.ReadContainerStreamAsync( diagnosticsContext: diagnosticsContext, cancellationToken: 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); using (ResponseMessage createResponse = await this.CreateContainerStreamAsync( diagnosticsContext, containerProperties, throughputProperties, requestOptions, cancellationToken)) { if (createResponse.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 using (ResponseMessage readResponseAfterCreate = await container.ReadContainerStreamAsync( diagnosticsContext: diagnosticsContext, cancellationToken: cancellationToken)) { return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, readResponseAfterCreate)); } }
public async Task <ContainerResponse> CreateContainerIfNotExistsAsync( CosmosDiagnosticsContext diagnosticsContext, ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions, ITrace trace, CancellationToken cancellationToken) { if (containerProperties == null) { throw new ArgumentNullException(nameof(containerProperties)); } this.ValidateContainerProperties(containerProperties); double totalRequestCharge = 0; ContainerCore container = (ContainerCore)this.GetContainer(containerProperties.Id); using (ResponseMessage readResponse = await container.ReadContainerStreamAsync( diagnosticsContext: diagnosticsContext, requestOptions: requestOptions, trace: trace, cancellationToken: cancellationToken)) { totalRequestCharge = readResponse.Headers.RequestCharge; if (readResponse.StatusCode != HttpStatusCode.NotFound) { ContainerResponse retrivedContainerResponse = this.ClientContext.ResponseFactory.CreateContainerResponse( container, readResponse); if (containerProperties.PartitionKey.Kind != Documents.PartitionKind.MultiHash) { if (!retrivedContainerResponse.Resource.PartitionKeyPath.Equals(containerProperties.PartitionKeyPath)) { throw new ArgumentException( string.Format( ClientResources.PartitionKeyPathConflict, containerProperties.PartitionKeyPath, containerProperties.Id, retrivedContainerResponse.Resource.PartitionKeyPath), nameof(containerProperties.PartitionKey)); } } #if INTERNAL || SUBPARTITIONING else { IReadOnlyList <string> retrivedPartitionKeyPaths = retrivedContainerResponse.Resource.PartitionKeyPaths; IReadOnlyList <string> receivedPartitionKeyPaths = containerProperties.PartitionKeyPaths; if (retrivedPartitionKeyPaths.Count != receivedPartitionKeyPaths.Count || !Enumerable.SequenceEqual(retrivedPartitionKeyPaths, receivedPartitionKeyPaths)) { throw new ArgumentException( string.Format( ClientResources.PartitionKeyPathConflict, string.Join(",", containerProperties.PartitionKeyPaths), containerProperties.Id, string.Join(",", retrivedContainerResponse.Resource.PartitionKeyPaths)), nameof(containerProperties.PartitionKey)); } } #endif return(retrivedContainerResponse); } } this.ValidateContainerProperties(containerProperties); using (ResponseMessage createResponse = await this.CreateContainerStreamAsync( diagnosticsContext, containerProperties, throughputProperties, requestOptions, trace, cancellationToken)) { totalRequestCharge += createResponse.Headers.RequestCharge; createResponse.Headers.RequestCharge = totalRequestCharge; if (createResponse.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 using (ResponseMessage readResponseAfterCreate = await container.ReadContainerStreamAsync( diagnosticsContext: diagnosticsContext, requestOptions: requestOptions, trace: trace, cancellationToken: cancellationToken)) { totalRequestCharge += readResponseAfterCreate.Headers.RequestCharge; readResponseAfterCreate.Headers.RequestCharge = totalRequestCharge; return(this.ClientContext.ResponseFactory.CreateContainerResponse(container, readResponseAfterCreate)); } }
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); Container container = this.GetContainer(containerProperties.Id); ResponseMessage readResponse = await container.ReadContainerStreamAsync( cancellationToken : cancellationToken); if (readResponse.StatusCode != HttpStatusCode.NotFound) { ContainerResponse retrivedContainerResponse = await this.ClientContext.ResponseFactory.CreateContainerResponseAsync( container, Task.FromResult(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(await this.ClientContext.ResponseFactory.CreateContainerResponseAsync(container, Task.FromResult(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 container.ReadContainerStreamAsync( cancellationToken : cancellationToken); // Merge the previous message diagnostics createResponse.DiagnosticsContext.AddDiagnosticsInternal(readResponse.DiagnosticsContext); return(await this.ClientContext.ResponseFactory.CreateContainerResponseAsync(container, Task.FromResult(readResponseAfterCreate))); }