private async Task <ResponseMessage> ProcessResourceOperationAsBulkStreamAsync(
            Uri resourceUri,
            ResourceType resourceType,
            OperationType operationType,
            RequestOptions requestOptions,
            ContainerCore cosmosContainerCore,
            PartitionKey partitionKey,
            string itemId,
            Stream streamPayload,
            CosmosDiagnosticsContext diagnosticsContext,
            CancellationToken cancellationToken)
        {
            ItemRequestOptions itemRequestOptions = requestOptions as ItemRequestOptions;
            TransactionalBatchItemRequestOptions batchItemRequestOptions = TransactionalBatchItemRequestOptions.FromItemRequestOptions(itemRequestOptions);
            ItemBatchOperation itemBatchOperation = new ItemBatchOperation(
                operationType: operationType,
                operationIndex: 0,
                partitionKey: partitionKey,
                id: itemId,
                resourceStream: streamPayload,
                requestOptions: batchItemRequestOptions,
                diagnosticsContext: diagnosticsContext);

            TransactionalBatchOperationResult batchOperationResult = await cosmosContainerCore.BatchExecutor.AddAsync(itemBatchOperation, itemRequestOptions, cancellationToken);

            return(batchOperationResult.ToResponseMessage());
        }
Beispiel #2
0
        internal static Result ReadOperationResult(Memory <byte> input, out TransactionalBatchOperationResult batchOperationResult)
        {
            RowBuffer row = new RowBuffer(input.Length);

            if (!row.ReadFrom(
                    input.Span,
                    HybridRowVersion.V1,
                    BatchSchemaProvider.BatchLayoutResolver))
            {
                batchOperationResult = null;
                return(Result.Failure);
            }

            RowReader reader = new RowReader(ref row);
            Result    result = TransactionalBatchOperationResult.ReadOperationResult(ref reader, out batchOperationResult);

            if (result != Result.Success)
            {
                return(result);
            }

            // Ensure the mandatory fields were populated
            if (batchOperationResult.StatusCode == default(HttpStatusCode))
            {
                return(Result.Failure);
            }

            return(Result.Success);
        }
        public void CanBeMocked()
        {
            Mock <TransactionalBatchOperationResult> mockResult = new Mock <TransactionalBatchOperationResult>();
            TransactionalBatchOperationResult        result     = mockResult.Object;

            Assert.AreEqual(default(HttpStatusCode), result.StatusCode);
        }
        private async Task <ResponseMessage> ProcessResourceOperationAsBulkStreamAsync(
            OperationType operationType,
            RequestOptions requestOptions,
            ContainerInternal cosmosContainerCore,
            PartitionKey partitionKey,
            string itemId,
            Stream streamPayload,
            CancellationToken cancellationToken)
        {
            this.ThrowIfDisposed();
            ItemRequestOptions itemRequestOptions = requestOptions as ItemRequestOptions;
            TransactionalBatchItemRequestOptions batchItemRequestOptions = TransactionalBatchItemRequestOptions.FromItemRequestOptions(itemRequestOptions);
            ItemBatchOperation itemBatchOperation = new ItemBatchOperation(
                operationType: operationType,
                operationIndex: 0,
                partitionKey: partitionKey,
                id: itemId,
                resourceStream: streamPayload,
                requestOptions: batchItemRequestOptions,
                cosmosClientContext: this);

            TransactionalBatchOperationResult batchOperationResult = await cosmosContainerCore.BatchExecutor.AddAsync(
                itemBatchOperation,
                itemRequestOptions,
                cancellationToken);

            return(batchOperationResult.ToResponseMessage());
        }
        public void GenericCanBeMocked()
        {
            Mock <TransactionalBatchOperationResult <object> > mockResult = new Mock <TransactionalBatchOperationResult <object> >();
            TransactionalBatchOperationResult <object>         result     = mockResult.Object;

            Assert.AreEqual(default(HttpStatusCode), result.StatusCode);
            Assert.AreEqual(default(object), result.Resource);
        }
 public void IsSuccessStatusCodeTrueFor200to299()
 {
     for (int x = 100; x < 999; ++x)
     {
         TransactionalBatchOperationResult result = new TransactionalBatchOperationResult((HttpStatusCode)x);
         bool success = x >= 200 && x <= 299;
         Assert.AreEqual(success, result.IsSuccessStatusCode);
     }
 }
Beispiel #7
0
 internal TransactionalBatchOperationResult(TransactionalBatchOperationResult other)
 {
     this.StatusCode     = other.StatusCode;
     this.SubStatusCode  = other.SubStatusCode;
     this.ETag           = other.ETag;
     this.ResourceStream = other.ResourceStream;
     this.RequestCharge  = other.RequestCharge;
     this.RetryAfter     = other.RetryAfter;
 }
Beispiel #8
0
        public void Complete(
            BatchAsyncBatcher completer,
            TransactionalBatchOperationResult result)
        {
            if (this.AssertBatcher(completer))
            {
                this.taskCompletionSource.SetResult(result);
            }

            this.Dispose();
        }
        public void PropertiesAreSetThroughCopyCtor()
        {
            TransactionalBatchOperationResult other  = CreateTestResult();
            TransactionalBatchOperationResult result = new TransactionalBatchOperationResult(other);

            Assert.AreEqual(other.StatusCode, result.StatusCode);
            Assert.AreEqual(other.SubStatusCode, result.SubStatusCode);
            Assert.AreEqual(other.ETag, result.ETag);
            Assert.AreEqual(other.RequestCharge, result.RequestCharge);
            Assert.AreEqual(other.RetryAfter, result.RetryAfter);
            Assert.AreSame(other.ResourceStream, result.ResourceStream);
        }
Beispiel #10
0
        public void Complete(
            BatchAsyncBatcher completer,
            TransactionalBatchOperationResult result)
        {
            if (this.AssertBatcher(completer))
            {
                this.initialTrace.AddChild(result.Trace);
                result.Trace = this.initialTrace;
                this.taskCompletionSource.SetResult(result);
            }

            this.Dispose();
        }
        public void ToResponseMessageHasPropertiesMapped()
        {
            TransactionalBatchOperationResult result = CreateTestResult();

            ResponseMessage response = result.ToResponseMessage();

            Assert.AreEqual(result.StatusCode, response.StatusCode);
            Assert.AreEqual(result.SubStatusCode, response.Headers.SubStatusCode);
            Assert.AreEqual(result.ETag, response.Headers.ETag);
            Assert.AreEqual(result.RequestCharge, response.Headers.RequestCharge);
            Assert.AreEqual(result.RetryAfter, response.Headers.RetryAfter);
            Assert.AreSame(result.ResourceStream, response.Content);
            Assert.AreSame(result.Diagnostics, response.Diagnostics);
        }
        public void PropertiesAreSetThroughGenericCtor()
        {
            TransactionalBatchOperationResult other = CreateTestResult();
            object testObject = new object();
            TransactionalBatchOperationResult <object> result = new TransactionalBatchOperationResult <object>(other, testObject);

            Assert.AreEqual(other.StatusCode, result.StatusCode);
            Assert.AreEqual(other.SubStatusCode, result.SubStatusCode);
            Assert.AreEqual(other.ETag, result.ETag);
            Assert.AreEqual(other.RequestCharge, result.RequestCharge);
            Assert.AreEqual(other.RetryAfter, result.RetryAfter);
            Assert.AreSame(other.ResourceStream, result.ResourceStream);
            Assert.AreSame(testObject, result.Resource);
        }
Beispiel #13
0
        /// <summary>
        /// Based on the Retry Policy, if a failed response should retry.
        /// </summary>
        public Task <ShouldRetryResult> ShouldRetryAsync(
            TransactionalBatchOperationResult batchOperationResult,
            CancellationToken cancellationToken)
        {
            if (this.retryPolicy == null ||
                batchOperationResult.IsSuccessStatusCode)
            {
                return(Task.FromResult(ShouldRetryResult.NoRetry()));
            }

            ResponseMessage responseMessage = batchOperationResult.ToResponseMessage();

            return(this.retryPolicy.ShouldRetryAsync(responseMessage, cancellationToken));
        }
        /// <summary>
        /// Gets the result of the operation at the provided index in the batch - the returned result has a Resource of provided type.
        /// </summary>
        /// <typeparam name="T">Type to which the Resource in the operation result needs to be deserialized to, when present.</typeparam>
        /// <param name="index">0-based index of the operation in the batch whose result needs to be returned.</param>
        /// <returns>Result of batch operation that contains a Resource deserialized to specified type.</returns>
        public override TransactionalBatchOperationResult <T> GetOperationResultAtIndex <T>(int index)
        {
            if (index >= this.Count)
            {
                throw new IndexOutOfRangeException();
            }

            TransactionalBatchOperationResult result = this.resultsByOperationIndex[index];

            T resource = default;

            if (result.ResourceStream != null)
            {
                resource = this.SerializerCore.FromStream <T>(result.ResourceStream);
            }

            return(new TransactionalBatchOperationResult <T>(result, resource));
        }
Beispiel #15
0
        private async Task <ResponseMessage> ProcessResourceOperationAsBulkStreamAsync(
            Uri resourceUri,
            ResourceType resourceType,
            OperationType operationType,
            RequestOptions requestOptions,
            ContainerCore cosmosContainerCore,
            PartitionKey partitionKey,
            string itemId,
            Stream streamPayload,
            Action <RequestMessage> requestEnricher,
            CancellationToken cancellationToken)
        {
            ItemRequestOptions itemRequestOptions = requestOptions as ItemRequestOptions;
            TransactionalBatchItemRequestOptions batchItemRequestOptions = TransactionalBatchItemRequestOptions.FromItemRequestOptions(itemRequestOptions);
            ItemBatchOperation itemBatchOperation = new ItemBatchOperation(operationType, /* index */ 0, partitionKey, itemId, streamPayload, batchItemRequestOptions);
            TransactionalBatchOperationResult batchOperationResult = await cosmosContainerCore.BatchExecutor.AddAsync(itemBatchOperation, itemRequestOptions, cancellationToken);

            return(batchOperationResult.ToResponseMessage());
        }
Beispiel #16
0
        /// <summary>
        /// Based on the Retry Policy, if a failed response should retry.
        /// </summary>
        public async Task <ShouldRetryResult> ShouldRetryAsync(
            TransactionalBatchOperationResult batchOperationResult,
            CancellationToken cancellationToken)
        {
            if (this.retryPolicy == null ||
                batchOperationResult.IsSuccessStatusCode)
            {
                return(ShouldRetryResult.NoRetry());
            }

            ResponseMessage   responseMessage = batchOperationResult.ToResponseMessage();
            ShouldRetryResult shouldRetry     = await this.retryPolicy.ShouldRetryAsync(responseMessage, cancellationToken);

            if (shouldRetry.ShouldRetry)
            {
                this.initialTrace.AddChild(batchOperationResult.Trace);
            }

            return(shouldRetry);
        }
        public void StatusCodeIsSetThroughCtor()
        {
            TransactionalBatchOperationResult result = new TransactionalBatchOperationResult(HttpStatusCode.Unused);

            Assert.AreEqual(HttpStatusCode.Unused, result.StatusCode);
        }
Beispiel #18
0
        private static Result ReadOperationResult(ref RowReader reader, out TransactionalBatchOperationResult batchOperationResult)
        {
            batchOperationResult = new TransactionalBatchOperationResult();
            while (reader.Read())
            {
                Result r;
                switch (reader.Path)
                {
                case "statusCode":
                    r = reader.ReadInt32(out int statusCode);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    batchOperationResult.StatusCode = (HttpStatusCode)statusCode;
                    break;

                case "subStatusCode":
                    r = reader.ReadInt32(out int subStatusCode);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    batchOperationResult.SubStatusCode = (SubStatusCodes)subStatusCode;
                    break;

                case "eTag":
                    r = reader.ReadString(out string eTag);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    batchOperationResult.ETag = eTag;
                    break;

                case "resourceBody":
                    r = reader.ReadBinary(out byte[] resourceBody);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    batchOperationResult.ResourceStream = new MemoryStream(
                        buffer: resourceBody, index: 0, count: resourceBody.Length, writable: false, publiclyVisible: true);
                    break;

                case "requestCharge":
                    r = reader.ReadFloat64(out double requestCharge);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    // Round request charge to 2 decimals on the operation results
                    // similar to how we round them for the full response.
                    batchOperationResult.RequestCharge = Math.Round(requestCharge, 2);
                    break;

                case "retryAfterMilliseconds":
                    r = reader.ReadUInt32(out uint retryAfterMilliseconds);
                    if (r != Result.Success)
                    {
                        return(r);
                    }

                    batchOperationResult.RetryAfter = TimeSpan.FromMilliseconds(retryAfterMilliseconds);
                    break;
                }
            }

            return(Result.Success);
        }
Beispiel #19
0
        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;
            }
        }
Beispiel #20
0
        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);

                    using (PartitionKeyRangeBatchResponse batchResponse = new PartitionKeyRangeBatchResponse(serverRequest.Operations.Count, result.ServerResponse, this.serializerCore))
                    {
                        foreach (ItemBatchOperation itemBatchOperation in batchResponse.Operations)
                        {
                            TransactionalBatchOperationResult response = batchResponse[itemBatchOperation.OperationIndex];
                            itemBatchOperation.Context.Diagnostics.AppendDiagnostics(batchResponse.Diagnostics);
                            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.dispached = true;
            }
        }