public virtual async Task DispatchAsync( BatchPartitionMetric partitionMetric, CancellationToken cancellationToken = default) { this.interlockIncrementCheck.EnterLockCheck(); PartitionKeyRangeServerBatchRequest serverRequest = null; ArraySegment <ItemBatchOperation> pendingOperations; try { try { // HybridRow serialization might leave some pending operations out of the batch Tuple <PartitionKeyRangeServerBatchRequest, ArraySegment <ItemBatchOperation> > createRequestResponse = await this.CreateServerRequestAsync(cancellationToken); serverRequest = createRequestResponse.Item1; pendingOperations = createRequestResponse.Item2; // Any overflow goes to a new batch foreach (ItemBatchOperation operation in pendingOperations) { await this.retrier(operation, cancellationToken); } } catch (Exception ex) { // Exceptions happening during request creation, fail the entire list foreach (ItemBatchOperation itemBatchOperation in this.batchOperations) { itemBatchOperation.Context.Fail(this, ex); } throw; } try { Stopwatch stopwatch = Stopwatch.StartNew(); PartitionKeyRangeBatchExecutionResult result = await this.executor(serverRequest, cancellationToken); int numThrottle = result.ServerResponse.Any(r => r.StatusCode == (System.Net.HttpStatusCode)StatusCodes.TooManyRequests) ? 1 : 0; partitionMetric.Add( numberOfDocumentsOperatedOn: result.ServerResponse.Count, timeTakenInMilliseconds: stopwatch.ElapsedMilliseconds, numberOfThrottles: numThrottle); using (PartitionKeyRangeBatchResponse batchResponse = new PartitionKeyRangeBatchResponse(serverRequest.Operations.Count, result.ServerResponse, this.serializerCore)) { foreach (ItemBatchOperation itemBatchOperation in batchResponse.Operations) { TransactionalBatchOperationResult response = batchResponse[itemBatchOperation.OperationIndex]; // Bulk has diagnostics per a item operation. // Batch has a single diagnostics for the execute operation if (itemBatchOperation.DiagnosticsContext != null) { response.DiagnosticsContext = itemBatchOperation.DiagnosticsContext; response.DiagnosticsContext.AddDiagnosticsInternal(batchResponse.DiagnosticsContext); } else { response.DiagnosticsContext = batchResponse.DiagnosticsContext; } if (!response.IsSuccessStatusCode) { Documents.ShouldRetryResult shouldRetry = await itemBatchOperation.Context.ShouldRetryAsync(response, cancellationToken); if (shouldRetry.ShouldRetry) { await this.retrier(itemBatchOperation, cancellationToken); continue; } } itemBatchOperation.Context.Complete(this, response); } } } catch (Exception ex) { // Exceptions happening during execution fail all the Tasks part of the request (excluding overflow) foreach (ItemBatchOperation itemBatchOperation in serverRequest.Operations) { itemBatchOperation.Context.Fail(this, ex); } throw; } } catch (Exception ex) { DefaultTrace.TraceError("Exception during BatchAsyncBatcher: {0}", ex); } finally { this.batchOperations.Clear(); this.dispatched = true; } }
public virtual async Task DispatchAsync(CancellationToken cancellationToken = default(CancellationToken)) { this.interlockIncrementCheck.EnterLockCheck(); PartitionKeyRangeServerBatchRequest serverRequest = null; ArraySegment <ItemBatchOperation> pendingOperations; try { try { // HybridRow serialization might leave some pending operations out of the batch Tuple <PartitionKeyRangeServerBatchRequest, ArraySegment <ItemBatchOperation> > createRequestResponse = await this.CreateServerRequestAsync(cancellationToken); serverRequest = createRequestResponse.Item1; pendingOperations = createRequestResponse.Item2; // Any overflow goes to a new batch foreach (ItemBatchOperation operation in pendingOperations) { await this.retrier(operation, cancellationToken); } } catch (Exception ex) { // Exceptions happening during request creation, fail the entire list foreach (ItemBatchOperation itemBatchOperation in this.batchOperations) { itemBatchOperation.Context.Fail(this, ex); } throw; } try { PartitionKeyRangeBatchExecutionResult result = await this.executor(serverRequest, cancellationToken); if (result.IsSplit()) { foreach (ItemBatchOperation operationToRetry in result.Operations) { await this.retrier(operationToRetry, cancellationToken); } return; } using (PartitionKeyRangeBatchResponse batchResponse = new PartitionKeyRangeBatchResponse(serverRequest.Operations.Count, result.ServerResponse, this.cosmosSerializer)) { foreach (ItemBatchOperation itemBatchOperation in batchResponse.Operations) { BatchOperationResult response = batchResponse[itemBatchOperation.OperationIndex]; itemBatchOperation.Context.Complete(this, response); } } } catch (Exception ex) { // Exceptions happening during execution fail all the Tasks part of the request (excluding overflow) foreach (ItemBatchOperation itemBatchOperation in serverRequest.Operations) { itemBatchOperation.Context.Fail(this, ex); } throw; } } catch (Exception ex) { DefaultTrace.TraceError("Exception during BatchAsyncBatcher: {0}", ex); } finally { this.batchOperations.Clear(); this.dispached = true; } }