public async Task DispatchesAsync()
        {
            // Expect all operations to complete as their batches get dispached
            BatchAsyncStreamer batchAsyncStreamer = new BatchAsyncStreamer(
                2,
                MaxBatchByteSize,
                this.TimerWheel,
                this.limiter,
                1,
                MockCosmosUtil.Serializer,
                this.Executor,
                this.Retrier,
                this.GetMockClientContext());
            List <Task <TransactionalBatchOperationResult> > contexts = new List <Task <TransactionalBatchOperationResult> >(10);

            for (int i = 0; i < 10; i++)
            {
                ItemBatchOperation        operation = new ItemBatchOperation(OperationType.Create, i, Cosmos.PartitionKey.Null, i.ToString());
                ItemBatchOperationContext context   = AttachContext(operation);
                batchAsyncStreamer.Add(operation);
                contexts.Add(context.OperationTask);
            }

            await Task.WhenAll(contexts);

            for (int i = 0; i < 10; i++)
            {
                Task <TransactionalBatchOperationResult> context = contexts[i];
                Assert.AreEqual(TaskStatus.RanToCompletion, context.Status);
                TransactionalBatchOperationResult result = await context;
                Assert.AreEqual(i.ToString(), result.ETag);
            }
        }
        public async Task DispatchProcessInOrderAsync()
        {
            BatchAsyncBatcher         batchAsyncBatcher = new BatchAsyncBatcher(10, 1000, new CosmosJsonDotNetSerializer(), this.Executor, this.Retrier);
            List <ItemBatchOperation> operations        = new List <ItemBatchOperation>(10);

            for (int i = 0; i < 10; i++)
            {
                ItemBatchOperation        operation = new ItemBatchOperation(OperationType.Create, i, i.ToString());
                ItemBatchOperationContext context   = new ItemBatchOperationContext(string.Empty);
                operation.AttachContext(context);
                operations.Add(operation);
                Assert.IsTrue(batchAsyncBatcher.TryAdd(operation));
            }

            await batchAsyncBatcher.DispatchAsync();

            for (int i = 0; i < 10; i++)
            {
                ItemBatchOperation operation = operations[i];
                Assert.AreEqual(TaskStatus.RanToCompletion, operation.Context.OperationTask.Status);
                BatchOperationResult result = await operation.Context.OperationTask;
                Assert.AreEqual(i.ToString(), result.ETag);

                Assert.IsNotNull(operation.Context.Diagnostics);
                Assert.AreEqual(operation.Context.Diagnostics.ToString(), result.Diagnostics.ToString());
                Assert.IsFalse(string.IsNullOrEmpty(operation.Context.Diagnostics.ToString()));
            }
        }
        public async Task DispatchProcessInOrderAsync()
        {
            BatchAsyncBatcher         batchAsyncBatcher = new BatchAsyncBatcher(10, 1000, MockCosmosUtil.Serializer, this.Executor, this.Retrier, BatchAsyncBatcherTests.MockClientContext());
            List <ItemBatchOperation> operations        = new List <ItemBatchOperation>(10);

            for (int i = 0; i < 10; i++)
            {
                ItemBatchOperation operation = new ItemBatchOperation(
                    operationType: OperationType.Create,
                    operationIndex: i,
                    partitionKey: new Cosmos.PartitionKey(i.ToString()),
                    id: i.ToString());

                ItemBatchOperationContext context = new ItemBatchOperationContext(string.Empty, NoOpTrace.Singleton);
                operation.AttachContext(context);
                operations.Add(operation);
                Assert.IsTrue(batchAsyncBatcher.TryAdd(operation));
            }

            await batchAsyncBatcher.DispatchAsync(metric);

            for (int i = 0; i < 10; i++)
            {
                ItemBatchOperation operation = operations[i];
                Assert.AreEqual(TaskStatus.RanToCompletion, operation.Context.OperationTask.Status);
                TransactionalBatchOperationResult result = await operation.Context.OperationTask;
                Assert.AreEqual(i.ToString(), result.ETag);
            }
        }
        private static ItemBatchOperationContext AttachContext(ItemBatchOperation operation)
        {
            ItemBatchOperationContext context = new ItemBatchOperationContext(string.Empty, NoOpTrace.Singleton);

            operation.AttachContext(context);
            return(context);
        }
        public async Task ExceptionsOnBatchBubbleUpAsync()
        {
            BatchAsyncStreamer        batchAsyncStreamer = new BatchAsyncStreamer(2, MaxBatchByteSize, this.TimerWheel, this.limiter, 1, MockCosmosUtil.Serializer, this.ExecutorWithFailure, this.Retrier, this.GetMockClientContext());
            ItemBatchOperationContext context            = AttachContext(this.ItemBatchOperation);

            batchAsyncStreamer.Add(this.ItemBatchOperation);
            Exception capturedException = await Assert.ThrowsExceptionAsync <Exception>(() => context.OperationTask);

            Assert.AreEqual(expectedException, capturedException);
        }
        public async Task ExceptionsOnBatchBubbleUpAsync()
        {
            BatchAsyncStreamer        batchAsyncStreamer = new BatchAsyncStreamer(2, MaxBatchByteSize, DispatchTimerInSeconds, this.TimerPool, new CosmosJsonDotNetSerializer(), this.ExecutorWithFailure, this.Retrier);
            ItemBatchOperationContext context            = AttachContext(this.ItemBatchOperation);

            batchAsyncStreamer.Add(this.ItemBatchOperation);
            Exception capturedException = await Assert.ThrowsExceptionAsync <Exception>(() => context.OperationTask);

            Assert.AreEqual(expectedException, capturedException);
        }
        public async Task TimerDispatchesAsync()
        {
            // Bigger batch size than the amount of operations, timer should dispatch
            BatchAsyncStreamer        batchAsyncStreamer = new BatchAsyncStreamer(2, MaxBatchByteSize, this.TimerWheel, this.limiter, 1, MockCosmosUtil.Serializer, this.Executor, this.Retrier, this.GetMockClientContext());
            ItemBatchOperationContext context            = AttachContext(this.ItemBatchOperation);

            batchAsyncStreamer.Add(this.ItemBatchOperation);
            TransactionalBatchOperationResult result = await context.OperationTask;

            Assert.AreEqual(this.ItemBatchOperation.Id, result.ETag);
        }
        public async Task TimerDispatchesAsync()
        {
            // Bigger batch size than the amount of operations, timer should dispatch
            BatchAsyncStreamer        batchAsyncStreamer = new BatchAsyncStreamer(2, MaxBatchByteSize, DispatchTimerInSeconds, this.TimerPool, new CosmosJsonDotNetSerializer(), this.Executor, this.Retrier);
            ItemBatchOperationContext context            = AttachContext(this.ItemBatchOperation);

            batchAsyncStreamer.Add(this.ItemBatchOperation);
            BatchOperationResult result = await context.OperationTask;

            Assert.AreEqual(this.ItemBatchOperation.Id, result.ETag);
        }
Beispiel #9
0
        public void TaskIsCreatedOnInitialization()
        {
            ItemBatchOperation        operation = new ItemBatchOperation(OperationType.Create, 0);
            ItemBatchOperationContext batchAsyncOperationContext = new ItemBatchOperationContext(string.Empty);

            operation.AttachContext(batchAsyncOperationContext);

            Assert.IsNotNull(batchAsyncOperationContext.OperationTask);
            Assert.AreEqual(batchAsyncOperationContext, operation.Context);
            Assert.AreEqual(TaskStatus.WaitingForActivation, batchAsyncOperationContext.OperationTask.Status);
        }
        public async Task DispatchWithLessResponses()
        {
            BatchAsyncBatcher         batchAsyncBatcher  = new BatchAsyncBatcher(10, 1000, MockCosmosUtil.Serializer, this.ExecutorWithLessResponses, this.Retrier, BatchAsyncBatcherTests.MockClientContext());
            BatchAsyncBatcher         secondAsyncBatcher = new BatchAsyncBatcher(10, 1000, MockCosmosUtil.Serializer, this.Executor, this.Retrier, BatchAsyncBatcherTests.MockClientContext());
            List <ItemBatchOperation> operations         = new List <ItemBatchOperation>(10);

            for (int i = 0; i < 10; i++)
            {
                ItemBatchOperation        operation = new ItemBatchOperation(OperationType.Create, i, Cosmos.PartitionKey.Null, i.ToString());
                ItemBatchOperationContext context   = new ItemBatchOperationContext(string.Empty, NoOpTrace.Singleton);
                operation.AttachContext(context);
                operations.Add(operation);
                Assert.IsTrue(batchAsyncBatcher.TryAdd(operation));
            }

            await batchAsyncBatcher.DispatchAsync(metric);

            // Responses 1 and 10 should be missing
            for (int i = 0; i < 10; i++)
            {
                ItemBatchOperation operation = operations[i];
                // Some tasks should not be resolved
                if (i == 0 || i == 9)
                {
                    Assert.IsTrue(operation.Context.OperationTask.Status == TaskStatus.WaitingForActivation);
                }
                else
                {
                    Assert.IsTrue(operation.Context.OperationTask.Status == TaskStatus.RanToCompletion);
                }
                if (operation.Context.OperationTask.Status == TaskStatus.RanToCompletion)
                {
                    TransactionalBatchOperationResult result = await operation.Context.OperationTask;
                    Assert.AreEqual(i.ToString(), result.ETag);
                }
                else
                {
                    // Pass the pending one to another batcher
                    Assert.IsTrue(secondAsyncBatcher.TryAdd(operation));
                }
            }

            await secondAsyncBatcher.DispatchAsync(metric);

            // All tasks should be completed
            for (int i = 0; i < 10; i++)
            {
                ItemBatchOperation operation = operations[i];
                Assert.AreEqual(TaskStatus.RanToCompletion, operation.Context.OperationTask.Status);
                TransactionalBatchOperationResult result = await operation.Context.OperationTask;
                Assert.AreEqual(i.ToString(), result.ETag);
            }
        }
Beispiel #11
0
        public void PartitionKeyRangeIdIsSetOnInitialization()
        {
            string                    expectedPkRangeId          = Guid.NewGuid().ToString();
            ItemBatchOperation        operation                  = new ItemBatchOperation(OperationType.Create, 0);
            ItemBatchOperationContext batchAsyncOperationContext = new ItemBatchOperationContext(expectedPkRangeId);

            operation.AttachContext(batchAsyncOperationContext);

            Assert.IsNotNull(batchAsyncOperationContext.OperationTask);
            Assert.AreEqual(batchAsyncOperationContext, operation.Context);
            Assert.AreEqual(expectedPkRangeId, batchAsyncOperationContext.PartitionKeyRangeId);
            Assert.AreEqual(TaskStatus.WaitingForActivation, batchAsyncOperationContext.OperationTask.Status);
        }
Beispiel #12
0
        public async Task TaskResultIsSetOnCompleteAsync()
        {
            ItemBatchOperation        operation = new ItemBatchOperation(OperationType.Create, 0);
            ItemBatchOperationContext batchAsyncOperationContext = new ItemBatchOperationContext(string.Empty);

            operation.AttachContext(batchAsyncOperationContext);

            BatchOperationResult expected = new BatchOperationResult(HttpStatusCode.OK);

            batchAsyncOperationContext.Complete(null, expected);

            Assert.AreEqual(expected, await batchAsyncOperationContext.OperationTask);
            Assert.AreEqual(TaskStatus.RanToCompletion, batchAsyncOperationContext.OperationTask.Status);
        }
Beispiel #13
0
        public async Task TaskResultIsSetOnCompleteAsync()
        {
            ItemBatchOperation        operation = new ItemBatchOperation(OperationType.Create, 0, Cosmos.PartitionKey.Null);
            ItemBatchOperationContext batchAsyncOperationContext = new ItemBatchOperationContext(string.Empty, NoOpTrace.Singleton);

            operation.AttachContext(batchAsyncOperationContext);

            TransactionalBatchOperationResult expected = new TransactionalBatchOperationResult(HttpStatusCode.OK);

            batchAsyncOperationContext.Complete(null, expected);

            Assert.AreEqual(expected, await batchAsyncOperationContext.OperationTask);
            Assert.AreEqual(TaskStatus.RanToCompletion, batchAsyncOperationContext.OperationTask.Status);
        }
Beispiel #14
0
        public async Task ExceptionIsSetOnFailAsync()
        {
            Exception                 failure   = new Exception("It failed");
            ItemBatchOperation        operation = new ItemBatchOperation(OperationType.Create, 0);
            ItemBatchOperationContext batchAsyncOperationContext = new ItemBatchOperationContext(string.Empty);

            operation.AttachContext(batchAsyncOperationContext);

            batchAsyncOperationContext.Fail(null, failure);

            Exception capturedException = await Assert.ThrowsExceptionAsync <Exception>(() => batchAsyncOperationContext.OperationTask);

            Assert.AreEqual(failure, capturedException);
            Assert.AreEqual(TaskStatus.Faulted, batchAsyncOperationContext.OperationTask.Status);
        }
        public async Task ExceptionsFailOperationsAsync()
        {
            BatchAsyncBatcher         batchAsyncBatcher = new BatchAsyncBatcher(2, 1000, new CosmosJsonDotNetSerializer(), this.ExecutorWithFailure, this.Retrier);
            ItemBatchOperation        operation1        = this.CreateItemBatchOperation();
            ItemBatchOperation        operation2        = this.CreateItemBatchOperation();
            ItemBatchOperationContext context1          = new ItemBatchOperationContext(string.Empty);

            operation1.AttachContext(context1);
            ItemBatchOperationContext context2 = new ItemBatchOperationContext(string.Empty);

            operation2.AttachContext(context2);
            batchAsyncBatcher.TryAdd(operation1);
            batchAsyncBatcher.TryAdd(operation2);
            await batchAsyncBatcher.DispatchAsync();

            Assert.AreEqual(TaskStatus.Faulted, context1.OperationTask.Status);
            Assert.AreEqual(TaskStatus.Faulted, context2.OperationTask.Status);
            Assert.AreEqual(expectedException, context1.OperationTask.Exception.InnerException);
            Assert.AreEqual(expectedException, context2.OperationTask.Exception.InnerException);
        }
        public async Task ExceptionsFailOperationsAsync()
        {
            BatchAsyncBatcher         batchAsyncBatcher = new BatchAsyncBatcher(2, 1000, MockCosmosUtil.Serializer, this.ExecutorWithFailure, this.Retrier, BatchAsyncBatcherTests.MockClientContext());
            ItemBatchOperation        operation1        = this.CreateItemBatchOperation();
            ItemBatchOperation        operation2        = this.CreateItemBatchOperation();
            ItemBatchOperationContext context1          = new ItemBatchOperationContext(string.Empty, NoOpTrace.Singleton);

            operation1.AttachContext(context1);
            ItemBatchOperationContext context2 = new ItemBatchOperationContext(string.Empty, NoOpTrace.Singleton);

            operation2.AttachContext(context2);
            batchAsyncBatcher.TryAdd(operation1);
            batchAsyncBatcher.TryAdd(operation2);
            await batchAsyncBatcher.DispatchAsync(metric);

            Assert.AreEqual(TaskStatus.Faulted, context1.OperationTask.Status);
            Assert.AreEqual(TaskStatus.Faulted, context2.OperationTask.Status);
            Assert.AreEqual(expectedException, context1.OperationTask.Exception.InnerException);
            Assert.AreEqual(expectedException, context2.OperationTask.Exception.InnerException);
        }
Beispiel #17
0
        public async Task TraceIsJoinedOnCompletionWithRetry()
        {
            IDocumentClientRetryPolicy retryPolicy = new BulkExecutionRetryPolicy(
                Mock.Of <ContainerInternal>(),
                OperationType.Read,
                new ResourceThrottleRetryPolicy(1));

            Trace rootTrace = Trace.GetRootTrace(name: "RootTrace");

            ItemBatchOperation operation = new ItemBatchOperation(OperationType.Create, 0, Cosmos.PartitionKey.Null);

            // Start with the base trace
            ItemBatchOperationContext batchAsyncOperationContext = new ItemBatchOperationContext(Guid.NewGuid().ToString(), rootTrace, retryPolicy);

            operation.AttachContext(batchAsyncOperationContext);

            // Simulate a retry scenario that should append to the context traces
            Trace retryTrace = Trace.GetRootTrace(name: "TransportTrace");
            TransactionalBatchOperationResult retryResult = new TransactionalBatchOperationResult(HttpStatusCode.TooManyRequests)
            {
                Trace = retryTrace
            };
            ShouldRetryResult shouldRetryResult = await batchAsyncOperationContext.ShouldRetryAsync(retryResult, default);

            Assert.IsTrue(shouldRetryResult.ShouldRetry);

            // Simulate the completion that should append to the context traces
            Trace transportTrace = Trace.GetRootTrace(name: "TransportTrace");
            TransactionalBatchOperationResult result = new TransactionalBatchOperationResult(HttpStatusCode.OK)
            {
                Trace = transportTrace
            };

            batchAsyncOperationContext.Complete(null, result);

            Assert.AreEqual(result, await batchAsyncOperationContext.OperationTask);
            Assert.AreEqual(2, result.Trace.Children.Count, "The final trace should have the initial trace, plus the retries, plus the final trace");
            Assert.AreEqual(rootTrace, result.Trace, "The first trace child should be the initial root");
            Assert.AreEqual(retryTrace, result.Trace.Children[0], "The second trace child should be the one from the retry");
            Assert.AreEqual(transportTrace, result.Trace.Children[1], "The third trace child should be the one from the final result");
        }
        public async Task ValidatesCongestionControlAsync()
        {
            SemaphoreSlim      newLimiter         = new SemaphoreSlim(1, defaultMaxDegreeOfConcurrency);
            BatchAsyncStreamer batchAsyncStreamer = new BatchAsyncStreamer(2, MaxBatchByteSize, this.TimerWheel, newLimiter, defaultMaxDegreeOfConcurrency, MockCosmosUtil.Serializer, this.Executor, this.Retrier, this.GetMockClientContext());

            Assert.AreEqual(newLimiter.CurrentCount, 1);

            List <Task <TransactionalBatchOperationResult> > contexts = new List <Task <TransactionalBatchOperationResult> >(100);

            for (int i = 0; i < 600; i++)
            {
                ItemBatchOperation        operation = new ItemBatchOperation(OperationType.Create, i, Cosmos.PartitionKey.Null, i.ToString());
                ItemBatchOperationContext context   = AttachContext(operation);
                batchAsyncStreamer.Add(operation);
                contexts.Add(context.OperationTask);
            }

            // 300 batch request should atleast sum up to 1000 ms barrier with wait time of 20ms in executor
            await Task.WhenAll(contexts);

            await Task.Delay(2000);

            Assert.IsTrue(newLimiter.CurrentCount >= 2, "Count of threads that can enter into semaphore should increase atleast by 1");
        }
        public async Task DispatchesAsync()
        {
            // Expect all operations to complete as their batches get dispached
            BatchAsyncStreamer batchAsyncStreamer        = new BatchAsyncStreamer(2, MaxBatchByteSize, DispatchTimerInSeconds, this.TimerPool, new CosmosJsonDotNetSerializer(), this.Executor, this.Retrier);
            List <Task <BatchOperationResult> > contexts = new List <Task <BatchOperationResult> >(10);

            for (int i = 0; i < 10; i++)
            {
                ItemBatchOperation        operation = new ItemBatchOperation(OperationType.Create, i, i.ToString());
                ItemBatchOperationContext context   = AttachContext(operation);
                batchAsyncStreamer.Add(operation);
                contexts.Add(context.OperationTask);
            }

            await Task.WhenAll(contexts);

            for (int i = 0; i < 10; i++)
            {
                Task <BatchOperationResult> context = contexts[i];
                Assert.AreEqual(TaskStatus.RanToCompletion, context.Status);
                BatchOperationResult result = await context;
                Assert.AreEqual(i.ToString(), result.ETag);
            }
        }