internal void Init( CosmosClientOptions clientOptions, DocumentClient documentClient) { this.ClientOptions = clientOptions; this.DocumentClient = documentClient; //Request pipeline ClientPipelineBuilder clientPipelineBuilder = new ClientPipelineBuilder( this, this.ClientOptions.CustomHandlers); this.RequestHandler = clientPipelineBuilder.Build(); CosmosSerializerCore serializerCore = CosmosSerializerCore.Create( this.ClientOptions.Serializer, this.ClientOptions.SerializerOptions); this.ResponseFactory = new CosmosResponseFactory(serializerCore); this.ClientContext = new ClientContextCore( client: this, clientOptions: this.ClientOptions, serializerCore: serializerCore, cosmosResponseFactory: this.ResponseFactory, requestHandler: this.RequestHandler, documentClient: this.DocumentClient); }
internal static ReadFeedResponse <TInput> CreateResponse <TInput>( ResponseMessage responseMessage, CosmosSerializerCore serializerCore, Documents.ResourceType resourceType) { using (responseMessage) { // ReadFeed can return 304 on some scenarios (Change Feed for example) if (responseMessage.StatusCode != HttpStatusCode.NotModified) { responseMessage.EnsureSuccessStatusCode(); } CosmosArray cosmosArray = null; if (responseMessage.Content != null) { cosmosArray = CosmosElementSerializer.ToCosmosElements( responseMessage.Content, resourceType, null); } ReadFeedResponse <TInput> readFeedResponse = new ReadFeedResponse <TInput>( httpStatusCode: responseMessage.StatusCode, cosmosArray: cosmosArray, serializerCore: serializerCore, responseMessageHeaders: responseMessage.Headers, diagnostics: responseMessage.Diagnostics); return(readFeedResponse); } }
internal void Init( CosmosClientOptions clientOptions, DocumentClient documentClient) { this.ClientOptions = clientOptions; this.DocumentClient = documentClient; //Request pipeline ClientPipelineBuilder clientPipelineBuilder = new ClientPipelineBuilder( this, this.ClientOptions.CustomHandlers); this.RequestHandler = clientPipelineBuilder.Build(); CosmosSerializerCore serializerCore = CosmosSerializerCore.Create( this.ClientOptions.Serializer, this.ClientOptions.SerializerOptions); this.ResponseFactory = new CosmosResponseFactory(serializerCore); this.ClientContext = new ClientContextCore( client: this, clientOptions: this.ClientOptions, serializerCore: serializerCore, cosmosResponseFactory: this.ResponseFactory, requestHandler: this.RequestHandler, documentClient: this.DocumentClient, userAgent: this.DocumentClient.ConnectionPolicy.UserAgentContainer.UserAgent, encryptionProcessor: new EncryptionProcessor(), dekCache: new DekCache()); }
internal static ReadFeedResponse <TInput> CreateResponse <TInput>( ResponseMessage responseMessage, CosmosSerializerCore serializerCore) { using (responseMessage) { // ReadFeed can return 304 on Change Feed responses if (responseMessage.StatusCode != HttpStatusCode.NotModified) { responseMessage.EnsureSuccessStatusCode(); } IReadOnlyCollection <TInput> resources = CosmosFeedResponseSerializer.FromFeedResponseStream <TInput>( serializerCore, responseMessage.Content); ReadFeedResponse <TInput> readFeedResponse = new ReadFeedResponse <TInput>( httpStatusCode: responseMessage.StatusCode, resources: resources, resourceCount: resources.Count, responseMessageHeaders: responseMessage.Headers, diagnostics: responseMessage.Diagnostics); return(readFeedResponse); } }
internal static ReadFeedResponse <TInput> CreateResponse <TInput>( ResponseMessage responseMessage, CosmosSerializerCore serializerCore, Documents.ResourceType resourceType) { using (responseMessage) { responseMessage.EnsureSuccessStatusCode(); CosmosArray cosmosArray = null; if (responseMessage.Content != null) { cosmosArray = CosmosElementSerializer.ToCosmosElements( responseMessage.Content, resourceType, null); } ReadFeedResponse <TInput> readFeedResponse = new ReadFeedResponse <TInput>( httpStatusCode: responseMessage.StatusCode, cosmosArray: cosmosArray, serializerCore: serializerCore, responseMessageHeaders: responseMessage.Headers, diagnostics: responseMessage.Diagnostics); return(readFeedResponse); } }
/// <summary> /// Materializes the operation's resource into a Memory{byte} wrapping a byte array. /// </summary> /// <param name="serializerCore">Serializer to serialize user provided objects to JSON.</param> /// <param name="cancellationToken"><see cref="CancellationToken"/> for cancellation.</param> internal virtual async Task MaterializeResourceAsync(CosmosSerializerCore serializerCore, CancellationToken cancellationToken) { if (this.body.IsEmpty && this.ResourceStream != null) { this.body = await BatchExecUtils.StreamToMemoryAsync(this.ResourceStream, cancellationToken); } }
public BatchAsyncBatcher( int maxBatchOperationCount, int maxBatchByteSize, CosmosSerializerCore serializerCore, BatchAsyncBatcherExecuteDelegate executor, BatchAsyncBatcherRetryDelegate retrier, CosmosClientContext clientContext) { if (maxBatchOperationCount < 1) { throw new ArgumentOutOfRangeException(nameof(maxBatchOperationCount)); } if (maxBatchByteSize < 1) { throw new ArgumentOutOfRangeException(nameof(maxBatchByteSize)); } this.batchOperations = new List <ItemBatchOperation>(maxBatchOperationCount); this.executor = executor ?? throw new ArgumentNullException(nameof(executor)); this.retrier = retrier ?? throw new ArgumentNullException(nameof(retrier)); this.maxBatchByteSize = maxBatchByteSize; this.maxBatchOperationCount = maxBatchOperationCount; this.serializerCore = serializerCore ?? throw new ArgumentNullException(nameof(serializerCore)); this.clientContext = clientContext; }
/// <summary> /// Initializes a new instance of the <see cref="SinglePartitionKeyServerBatchRequest"/> class. /// Single partition key server request. /// </summary> /// <param name="partitionKey">Partition key that applies to all operations in this request.</param> /// <param name="serializerCore">Serializer to serialize user provided objects to JSON.</param> private SinglePartitionKeyServerBatchRequest( PartitionKey?partitionKey, CosmosSerializerCore serializerCore) : base(maxBodyLength: int.MaxValue, maxOperationCount: int.MaxValue, serializerCore: serializerCore) { this.PartitionKey = partitionKey; }
/// <summary> /// Initializes a new instance of the <see cref="PartitionKeyRangeServerBatchRequest"/> class. /// </summary> /// <param name="partitionKeyRangeId">The partition key range id associated with all requests.</param> /// <param name="maxBodyLength">Maximum length allowed for the request body.</param> /// <param name="maxOperationCount">Maximum number of operations allowed in the request.</param> /// <param name="serializerCore">Serializer to serialize user provided objects to JSON.</param> public PartitionKeyRangeServerBatchRequest( string partitionKeyRangeId, int maxBodyLength, int maxOperationCount, CosmosSerializerCore serializerCore) : base(maxBodyLength, maxOperationCount, serializerCore) { this.PartitionKeyRangeId = partitionKeyRangeId; }
/// <summary> /// Used for unit testing only. /// </summary> /// <remarks>This constructor should be removed at some point. The mocking should happen in a derivied class.</remarks> internal CosmosClient( string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions cosmosClientOptions, DocumentClient documentClient) { if (accountEndpoint == null) { throw new ArgumentNullException(nameof(accountEndpoint)); } if (authKeyOrResourceToken == null) { throw new ArgumentNullException(nameof(authKeyOrResourceToken)); } if (cosmosClientOptions == null) { throw new ArgumentNullException(nameof(cosmosClientOptions)); } if (documentClient == null) { throw new ArgumentNullException(nameof(documentClient)); } this.Endpoint = new Uri(accountEndpoint); this.AccountKey = authKeyOrResourceToken; this.ClientOptions = cosmosClientOptions; this.DocumentClient = documentClient; //Request pipeline ClientPipelineBuilder clientPipelineBuilder = new ClientPipelineBuilder( this, this.ClientOptions.CustomHandlers); this.RequestHandler = clientPipelineBuilder.Build(); CosmosSerializerCore serializerCore = CosmosSerializerCore.Create( this.ClientOptions.Serializer, this.ClientOptions.SerializerOptions); this.ResponseFactory = new CosmosResponseFactory(serializerCore); this.ClientContext = new ClientContextCore( client: this, clientOptions: this.ClientOptions, serializerCore: serializerCore, cosmosResponseFactory: this.ResponseFactory, requestHandler: this.RequestHandler, documentClient: this.DocumentClient, userAgent: this.DocumentClient.ConnectionPolicy.UserAgentContainer.UserAgent, encryptionProcessor: new EncryptionProcessor(), dekCache: new DekCache()); }
/// <summary> /// Creates an instance of <see cref="SinglePartitionKeyServerBatchRequest"/>. /// The body of the request is populated with operations till it reaches the provided maxBodyLength. /// </summary> /// <param name="partitionKey">Partition key of the request.</param> /// <param name="operations">Operations to be added into this batch request.</param> /// <param name="serializerCore">Serializer to serialize user provided objects to JSON.</param> /// <param name="cancellationToken"><see cref="CancellationToken"/> representing request cancellation.</param> /// <returns>A newly created instance of <see cref="SinglePartitionKeyServerBatchRequest"/>.</returns> public static async Task <SinglePartitionKeyServerBatchRequest> CreateAsync( PartitionKey?partitionKey, ArraySegment <ItemBatchOperation> operations, CosmosSerializerCore serializerCore, CancellationToken cancellationToken) { SinglePartitionKeyServerBatchRequest request = new SinglePartitionKeyServerBatchRequest(partitionKey, serializerCore); await request.CreateBodyStreamAsync(operations, cancellationToken); return(request); }
/// <summary> /// Initializes a new instance of the <see cref="PartitionKeyRangeServerBatchRequest"/> class. /// </summary> /// <param name="partitionKeyRangeId">The partition key range id associated with all requests.</param> /// <param name="isClientEncrypted"> If the operation has Encrypted data. </param> /// <param name="intendedCollectionRidValue"> Intended Collection Rid value. </param> /// <param name="maxBodyLength">Maximum length allowed for the request body.</param> /// <param name="maxOperationCount">Maximum number of operations allowed in the request.</param> /// <param name="serializerCore">Serializer to serialize user provided objects to JSON.</param> public PartitionKeyRangeServerBatchRequest( string partitionKeyRangeId, bool isClientEncrypted, string intendedCollectionRidValue, int maxBodyLength, int maxOperationCount, CosmosSerializerCore serializerCore) : base(maxBodyLength, maxOperationCount, serializerCore) { this.PartitionKeyRangeId = partitionKeyRangeId; this.IsClientEncrypted = isClientEncrypted; this.IntendedCollectionRidValue = intendedCollectionRidValue; }
public BatchAsyncStreamer( int maxBatchOperationCount, int maxBatchByteSize, int dispatchTimerInSeconds, TimerPool timerPool, CosmosSerializerCore serializerCore, BatchAsyncBatcherExecuteDelegate executor, BatchAsyncBatcherRetryDelegate retrier) { if (maxBatchOperationCount < 1) { throw new ArgumentOutOfRangeException(nameof(maxBatchOperationCount)); } if (maxBatchByteSize < 1) { throw new ArgumentOutOfRangeException(nameof(maxBatchByteSize)); } if (dispatchTimerInSeconds < 1) { throw new ArgumentOutOfRangeException(nameof(dispatchTimerInSeconds)); } if (executor == null) { throw new ArgumentNullException(nameof(executor)); } if (retrier == null) { throw new ArgumentNullException(nameof(retrier)); } if (serializerCore == null) { throw new ArgumentNullException(nameof(serializerCore)); } this.maxBatchOperationCount = maxBatchOperationCount; this.maxBatchByteSize = maxBatchByteSize; this.executor = executor; this.retrier = retrier; this.dispatchTimerInSeconds = dispatchTimerInSeconds; this.timerPool = timerPool; this.serializerCore = serializerCore; this.currentBatcher = this.CreateBatchAsyncBatcher(); this.ResetTimer(); }
/// <summary> /// Creates an instance of <see cref="PartitionKeyRangeServerBatchRequest"/>. /// In case of direct mode requests, all the operations are expected to belong to the same PartitionKeyRange. /// The body of the request is populated with operations till it reaches the provided maxBodyLength. /// </summary> /// <param name="partitionKeyRangeId">The partition key range id associated with all requests.</param> /// <param name="operations">Operations to be added into this batch request.</param> /// <param name="maxBodyLength">Desired maximum length of the request body.</param> /// <param name="maxOperationCount">Maximum number of operations allowed in the request.</param> /// <param name="ensureContinuousOperationIndexes">Whether to stop adding operations to the request once there is non-continuity in the operation indexes.</param> /// <param name="serializerCore">Serializer to serialize user provided objects to JSON.</param> /// <param name="cancellationToken"><see cref="CancellationToken"/> representing request cancellation.</param> /// <returns>A newly created instance of <see cref="PartitionKeyRangeServerBatchRequest"/> and the overflow ItemBatchOperation not being processed.</returns> public static async Task <Tuple <PartitionKeyRangeServerBatchRequest, ArraySegment <ItemBatchOperation> > > CreateAsync( string partitionKeyRangeId, ArraySegment <ItemBatchOperation> operations, int maxBodyLength, int maxOperationCount, bool ensureContinuousOperationIndexes, CosmosSerializerCore serializerCore, CancellationToken cancellationToken) { PartitionKeyRangeServerBatchRequest request = new PartitionKeyRangeServerBatchRequest(partitionKeyRangeId, maxBodyLength, maxOperationCount, serializerCore); ArraySegment <ItemBatchOperation> pendingOperations = await request.CreateBodyStreamAsync(operations, cancellationToken, ensureContinuousOperationIndexes); return(new Tuple <PartitionKeyRangeServerBatchRequest, ArraySegment <ItemBatchOperation> >(request, pendingOperations)); }
protected ReadFeedResponse( HttpStatusCode httpStatusCode, CosmosArray cosmosArray, CosmosSerializerCore serializerCore, Headers responseMessageHeaders, CosmosDiagnostics diagnostics) { this.Count = cosmosArray.Count; this.Headers = responseMessageHeaders; this.StatusCode = httpStatusCode; this.Diagnostics = diagnostics; this.Resource = CosmosElementSerializer.GetResources <T>( cosmosArray: cosmosArray, serializerCore: serializerCore); }
internal ClientContextCore( CosmosClient client, CosmosClientOptions clientOptions, CosmosSerializerCore serializerCore, CosmosResponseFactory cosmosResponseFactory, RequestInvokerHandler requestHandler, DocumentClient documentClient) { this.Client = client; this.ClientOptions = clientOptions; this.SerializerCore = serializerCore; this.ResponseFactory = cosmosResponseFactory; this.RequestHandler = requestHandler; this.DocumentClient = documentClient; }
/// <summary> /// Creates an instance of <see cref="SinglePartitionKeyServerBatchRequest"/>. /// The body of the request is populated with operations till it reaches the provided maxBodyLength. /// </summary> /// <param name="partitionKey">Partition key of the request.</param> /// <param name="operations">Operations to be added into this batch request.</param> /// <param name="serializerCore">Serializer to serialize user provided objects to JSON.</param> /// <param name="trace">The trace.</param> /// <param name="cancellationToken"><see cref="CancellationToken"/> representing request cancellation.</param> /// <returns>A newly created instance of <see cref="SinglePartitionKeyServerBatchRequest"/>.</returns> public static async Task <SinglePartitionKeyServerBatchRequest> CreateAsync( PartitionKey?partitionKey, ArraySegment <ItemBatchOperation> operations, CosmosSerializerCore serializerCore, ITrace trace, CancellationToken cancellationToken) { using (trace.StartChild("Create Batch Request", TraceComponent.Batch, TraceLevel.Info)) { SinglePartitionKeyServerBatchRequest request = new SinglePartitionKeyServerBatchRequest(partitionKey, serializerCore); await request.CreateBodyStreamAsync(operations, cancellationToken); return(request); } }
internal static CosmosClientContext Create( CosmosClient cosmosClient, DocumentClient documentClient, CosmosClientOptions clientOptions, RequestInvokerHandler requestInvokerHandler = null) { if (cosmosClient == null) { throw new ArgumentNullException(nameof(cosmosClient)); } if (documentClient == null) { throw new ArgumentNullException(nameof(documentClient)); } clientOptions = ClientContextCore.CreateOrCloneClientOptions(clientOptions); if (requestInvokerHandler == null) { //Request pipeline ClientPipelineBuilder clientPipelineBuilder = new ClientPipelineBuilder( cosmosClient, clientOptions.ConsistencyLevel, clientOptions.CustomHandlers); requestInvokerHandler = clientPipelineBuilder.Build(); } CosmosSerializerCore serializerCore = CosmosSerializerCore.Create( clientOptions.Serializer, clientOptions.SerializerOptions); // This sets the serializer on client options which gives users access to it if a custom one is not configured. clientOptions.SetSerializerIfNotConfigured(serializerCore.GetCustomOrDefaultSerializer()); CosmosResponseFactoryInternal responseFactory = new CosmosResponseFactoryCore(serializerCore); return(new ClientContextCore( client: cosmosClient, clientOptions: clientOptions, serializerCore: serializerCore, cosmosResponseFactory: responseFactory, requestHandler: requestInvokerHandler, documentClient: documentClient, userAgent: documentClient.ConnectionPolicy.UserAgentContainer.UserAgent, batchExecutorCache: new BatchAsyncContainerExecutorCache())); }
internal static CosmosClientContext Create( CosmosClient cosmosClient, DocumentClient documentClient, CosmosClientOptions clientOptions, RequestInvokerHandler requestInvokerHandler = null) { if (cosmosClient == null) { throw new ArgumentNullException(nameof(cosmosClient)); } if (documentClient == null) { throw new ArgumentNullException(nameof(documentClient)); } clientOptions = ClientContextCore.CreateOrCloneClientOptions(clientOptions); if (requestInvokerHandler == null) { //Request pipeline ClientPipelineBuilder clientPipelineBuilder = new ClientPipelineBuilder( cosmosClient, clientOptions.ConsistencyLevel, clientOptions.CustomHandlers); requestInvokerHandler = clientPipelineBuilder.Build(); } CosmosSerializerCore serializerCore = CosmosSerializerCore.Create( clientOptions.Serializer, clientOptions.SerializerOptions); CosmosResponseFactory responseFactory = new CosmosResponseFactory(serializerCore); return(new ClientContextCore( client: cosmosClient, clientOptions: clientOptions, serializerCore: serializerCore, cosmosResponseFactory: responseFactory, requestHandler: requestInvokerHandler, documentClient: documentClient, userAgent: documentClient.ConnectionPolicy.UserAgentContainer.UserAgent, encryptionProcessor: new EncryptionProcessor(), dekCache: new DekCache(), batchExecutorCache: new BatchAsyncContainerExecutorCache())); }
private TransactionalBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, Headers headers, ITrace trace, IReadOnlyList <ItemBatchOperation> operations, CosmosSerializerCore serializer) { this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.ErrorMessage = errorMessage; this.Operations = operations; this.SerializerCore = serializer; this.Headers = headers; this.Diagnostics = new CosmosTraceDiagnostics(trace ?? NoOpTrace.Singleton); }
private TransactionalBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, Headers headers, CosmosDiagnosticsContext diagnosticsContext, IReadOnlyList <ItemBatchOperation> operations, CosmosSerializerCore serializer) { this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.ErrorMessage = errorMessage; this.Operations = operations; this.SerializerCore = serializer; this.Headers = headers; this.Diagnostics = diagnosticsContext.Diagnostics; this.DiagnosticsContext = diagnosticsContext ?? throw new ArgumentNullException(nameof(diagnosticsContext)); }
/// <summary> /// Encrypts (if encryption options are set) and materializes the operation's resource into a Memory{byte} wrapping a byte array. /// </summary> /// <param name="serializerCore">Serializer to serialize user provided objects to JSON.</param> /// <param name="cancellationToken"><see cref="CancellationToken"/> for cancellation.</param> internal virtual async Task EncryptAndMaterializeResourceAsync(CosmosSerializerCore serializerCore, CancellationToken cancellationToken) { if (this.body.IsEmpty && this.ResourceStream != null) { Stream stream = this.ResourceStream; if (this.ContainerCore != null && this.RequestOptions?.EncryptionOptions != null) { stream = await this.ContainerCore.ClientContext.EncryptItemAsync( stream, this.RequestOptions.EncryptionOptions, (DatabaseCore)this.ContainerCore.Database, this.DiagnosticsContext, cancellationToken); } this.body = await BatchExecUtils.StreamToMemoryAsync(stream, cancellationToken); } }
private ClientContextCore( CosmosClient client, CosmosClientOptions clientOptions, CosmosSerializerCore serializerCore, CosmosResponseFactoryInternal cosmosResponseFactory, RequestInvokerHandler requestHandler, DocumentClient documentClient, string userAgent, BatchAsyncContainerExecutorCache batchExecutorCache) { this.client = client; this.clientOptions = clientOptions; this.serializerCore = serializerCore; this.responseFactory = cosmosResponseFactory; this.requestHandler = requestHandler; this.documentClient = documentClient; this.userAgent = userAgent; this.batchExecutorCache = batchExecutorCache; }
internal static ReadFeedResponse <TInput> CreateResponse <TInput>( ResponseMessage responseMessage, CosmosSerializerCore serializerCore) { using (responseMessage) { responseMessage.EnsureSuccessStatusCode(); IReadOnlyCollection <TInput> resources = CosmosFeedResponseSerializer.FromFeedResponseStream <TInput>( serializerCore, responseMessage.Content); ReadFeedResponse <TInput> readFeedResponse = new ReadFeedResponse <TInput>( httpStatusCode: responseMessage.StatusCode, resources: resources, responseMessageHeaders: responseMessage.Headers, diagnostics: responseMessage.Diagnostics); return(readFeedResponse); } }
internal ClientContextCore( CosmosClient client, CosmosClientOptions clientOptions, CosmosSerializerCore serializerCore, CosmosResponseFactory cosmosResponseFactory, RequestInvokerHandler requestHandler, DocumentClient documentClient, string userAgent, EncryptionProcessor encryptionProcessor = null, DekCache dekCache = null) { this.Client = client; this.ClientOptions = clientOptions; this.SerializerCore = serializerCore; this.ResponseFactory = cosmosResponseFactory; this.RequestHandler = requestHandler; this.DocumentClient = documentClient; this.UserAgent = userAgent; this.EncryptionProcessor = encryptionProcessor; this.DekCache = dekCache; }
private TransactionalBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, double requestCharge, TimeSpan?retryAfter, string activityId, CosmosDiagnostics cosmosDiagnostics, IReadOnlyList <ItemBatchOperation> operations, CosmosSerializerCore serializer) { this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.ErrorMessage = errorMessage; this.Operations = operations; this.SerializerCore = serializer; this.RequestCharge = requestCharge; this.RetryAfter = retryAfter; this.ActivityId = activityId; this.Diagnostics = cosmosDiagnostics; }
private TransactionalBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, double requestCharge, TimeSpan?retryAfter, string activityId, CosmosDiagnosticsContext diagnosticsContext, IReadOnlyList <ItemBatchOperation> operations, CosmosSerializerCore serializer) { this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.ErrorMessage = errorMessage; this.Operations = operations; this.SerializerCore = serializer; this.RequestCharge = requestCharge; this.RetryAfter = retryAfter; this.ActivityId = activityId; this.Diagnostics = diagnosticsContext.Diagnostics; this.DiagnosticsContext = diagnosticsContext ?? throw new ArgumentNullException(nameof(diagnosticsContext)); }
/// <summary> /// Initializes a new instance of the <see cref="PartitionKeyRangeBatchResponse"/> class. /// </summary> /// <param name="originalOperationsCount">Original operations that generated the server responses.</param> /// <param name="serverResponse">Response from the server.</param> /// <param name="serializerCore">Serializer to deserialize response resource body streams.</param> internal PartitionKeyRangeBatchResponse( int originalOperationsCount, TransactionalBatchResponse serverResponse, CosmosSerializerCore serializerCore) { this.StatusCode = serverResponse.StatusCode; this.serverResponse = serverResponse; this.resultsByOperationIndex = new TransactionalBatchOperationResult[originalOperationsCount]; StringBuilder errorMessageBuilder = new StringBuilder(); List <ItemBatchOperation> itemBatchOperations = new List <ItemBatchOperation>(); // We expect number of results == number of operations here for (int index = 0; index < serverResponse.Operations.Count; index++) { int operationIndex = serverResponse.Operations[index].OperationIndex; if (this.resultsByOperationIndex[operationIndex] == null || this.resultsByOperationIndex[operationIndex].StatusCode == (HttpStatusCode)StatusCodes.TooManyRequests) { this.resultsByOperationIndex[operationIndex] = serverResponse[index]; } } itemBatchOperations.AddRange(serverResponse.Operations); this.Headers = serverResponse.Headers; if (!string.IsNullOrEmpty(serverResponse.ErrorMessage)) { errorMessageBuilder.AppendFormat("{0}; ", serverResponse.ErrorMessage); } this.ErrorMessage = errorMessageBuilder.Length > 2 ? errorMessageBuilder.ToString(0, errorMessageBuilder.Length - 2) : null; this.Operations = itemBatchOperations; this.SerializerCore = serializerCore; }
private static async Task <TransactionalBatchResponse> PopulateFromContentAsync( Stream content, ResponseMessage responseMessage, ServerBatchRequest serverRequest, CosmosSerializerCore serializer, ITrace trace, bool shouldPromoteOperationStatus) { List <TransactionalBatchOperationResult> results = new List <TransactionalBatchOperationResult>(); // content is ensured to be seekable in caller. int resizerInitialCapacity = (int)content.Length; Result res = await content.ReadRecordIOAsync( (Func <ReadOnlyMemory <byte>, Result>)(record => { Result r = TransactionalBatchOperationResult.ReadOperationResult(record, out TransactionalBatchOperationResult operationResult); if (r != Result.Success) { return(r); } operationResult.Trace = trace; results.Add(operationResult); return(r); }), resizer : new MemorySpanResizer <byte>(resizerInitialCapacity)); if (res != Result.Success) { return(null); } HttpStatusCode responseStatusCode = responseMessage.StatusCode; SubStatusCodes responseSubStatusCode = responseMessage.Headers.SubStatusCode; // Promote the operation error status as the Batch response error status if we have a MultiStatus response // to provide users with status codes they are used to. if ((int)responseMessage.StatusCode == (int)StatusCodes.MultiStatus && shouldPromoteOperationStatus) { foreach (TransactionalBatchOperationResult result in results) { if ((int)result.StatusCode != (int)StatusCodes.FailedDependency && (int)result.StatusCode >= (int)StatusCodes.StartingErrorCode) { responseStatusCode = result.StatusCode; responseSubStatusCode = result.SubStatusCode; break; } } } TransactionalBatchResponse response = new TransactionalBatchResponse( responseStatusCode, responseSubStatusCode, responseMessage.ErrorMessage, responseMessage.Headers, trace, serverRequest.Operations, serializer) { results = results }; return(response); }
internal static async Task <TransactionalBatchResponse> FromResponseMessageAsync( ResponseMessage responseMessage, ServerBatchRequest serverRequest, CosmosSerializerCore serializer, bool shouldPromoteOperationStatus, ITrace trace, CancellationToken cancellationToken) { using (ITrace createResponseTrace = trace.StartChild("Create Trace", TraceComponent.Batch, TraceLevel.Info)) { 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, trace, shouldPromoteOperationStatus); if (response == null) { // Convert any payload read failures as InternalServerError response = new TransactionalBatchResponse( HttpStatusCode.InternalServerError, SubStatusCodes.Unknown, ClientResources.ServerResponseDeserializationFailure, responseMessage.Headers, trace, serverRequest.Operations, serializer); } } } if (response == null) { response = new TransactionalBatchResponse( responseMessage.StatusCode, responseMessage.Headers.SubStatusCode, responseMessage.ErrorMessage, responseMessage.Headers, trace, 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, trace, 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, trace, retryAfterMilliseconds); } return(response); } } }