예제 #1
0
        private static async Task VerifyExceptionThrownOnExecuteAsync(
            TransactionalBatch batch,
            Type expectedTypeOfException,
            string expectedExceptionMessage = null,
            TransactionalBatchRequestOptions requestOptions = null)
        {
            bool wasExceptionThrown = false;

            try
            {
                if (requestOptions != null)
                {
                    await batch.ExecuteAsync(requestOptions);
                }
                else
                {
                    await batch.ExecuteAsync();
                }
            }
            catch (Exception ex)
            {
                Assert.AreEqual(expectedTypeOfException, ex.GetType());
                if (expectedExceptionMessage != null)
                {
                    Assert.IsTrue(ex.Message.Contains(expectedExceptionMessage));
                }
                wasExceptionThrown = true;
            }

            if (!wasExceptionThrown)
            {
                Assert.Fail("Exception was expected to be thrown but was not.");
            }
        }
        public async Task ItemBatchNoResponseTest()
        {
            TransactionalBatchItemRequestOptions requestOptions = new TransactionalBatchItemRequestOptions()
            {
                EnableContentResponseOnWrite = false
            };

            string             pkId  = "TestBatchId";
            TransactionalBatch batch = this.container.CreateTransactionalBatch(new PartitionKey(pkId));

            int noResponseItemCount = 100;

            for (int i = 0; i < noResponseItemCount; i++)
            {
                ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(pk: pkId);
                batch.CreateItem <ToDoActivity>(item, requestOptions: requestOptions);
            }

            TransactionalBatchResponse response = await batch.ExecuteAsync();

            Assert.AreEqual(100, response.Count);
            this.ValidateResponse(response, noResponseItemCount);

            pkId  = "TestBatchId2";
            batch = this.container.CreateTransactionalBatch(new PartitionKey(pkId));

            noResponseItemCount = 0;
            for (int i = 0; i < 10; i++)
            {
                ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(pk: pkId);
                batch.CreateItem <ToDoActivity>(item, requestOptions: requestOptions);
                noResponseItemCount++;
                ToDoActivity item2 = ToDoActivity.CreateRandomToDoActivity(pk: pkId);
                item2.id = item.id;
                batch.ReplaceItem <ToDoActivity>(item2.id, item2, requestOptions);
                noResponseItemCount++;
            }

            int withBodyCount = 0;

            for (int i = 0; i < 5; i++)
            {
                ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(pk: pkId);
                batch.CreateItem <ToDoActivity>(item);
                withBodyCount++;
                batch.ReadItem(item.id);
                withBodyCount++;
            }

            response = await batch.ExecuteAsync();

            Assert.AreEqual(noResponseItemCount + withBodyCount, response.Count);
            this.ValidateResponse(response, noResponseItemCount);
        }
예제 #3
0
        public async Task NoContentResponseTransactionBatchOverrideTest()
        {
            string             pkId  = "TestBatchId";
            TransactionalBatch batch = this.containerWithFlag.CreateTransactionalBatch(new PartitionKey(pkId));
            TransactionalBatchItemRequestOptions requestOptions = new TransactionalBatchItemRequestOptions()
            {
                EnableContentResponseOnWrite = false
            };

            int noResponseItemCount = 100;

            for (int i = 0; i < noResponseItemCount; i++)
            {
                ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(pk: pkId);
                batch.CreateItem <ToDoActivity>(item, requestOptions: requestOptions);
            }

            TransactionalBatchResponse response = await batch.ExecuteAsync();

            Assert.AreEqual(response.Count, 100);
            foreach (TransactionalBatchOperationResult itemResponse in response)
            {
                Assert.IsTrue(itemResponse.StatusCode == HttpStatusCode.Created);
                Assert.IsNull(itemResponse.ResourceStream);
            }
        }
        public async Task BatchOperationDiagnostic(bool disableDiagnostics)
        {
            string                pkValue   = "DiagnosticTestPk";
            TransactionalBatch    batch     = this.Container.CreateTransactionalBatch(new PartitionKey(pkValue));
            BatchCore             batchCore = (BatchCore)batch;
            List <PatchOperation> patch     = new List <PatchOperation>()
            {
                PatchOperation.Remove("/cost")
            };

            List <ToDoActivity> createItems = new List <ToDoActivity>();

            for (int i = 0; i < 50; i++)
            {
                ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(pk: pkValue);
                createItems.Add(item);
                batch.CreateItem <ToDoActivity>(item);
            }

            for (int i = 0; i < 20; i++)
            {
                batch.ReadItem(createItems[i].id);
                batchCore.PatchItem(createItems[i].id, patch);
            }

            TransactionalBatchRequestOptions requestOptions = disableDiagnostics ? RequestOptionDisableDiagnostic : null;
            TransactionalBatchResponse       response       = await batch.ExecuteAsync(requestOptions);

            Assert.IsNotNull(response);
            CosmosDiagnosticsTests.VerifyPointDiagnostics(
                diagnostics: response.Diagnostics,
                disableDiagnostics: disableDiagnostics);
        }
예제 #5
0
        public async Task ExecuteAsync(Container collection)
        {
            EnsureArg.IsNotNull(collection, nameof(collection));

            // Detect if registry has been initialized
            var partitionKey = new PartitionKey(SearchParameterStatusWrapper.SearchParameterStatusPartitionKey);
            var query        = _queryFactory.Create <dynamic>(
                collection,
                new CosmosQueryContext(
                    new QueryDefinition($"SELECT TOP 1 * FROM c where c.{KnownDocumentProperties.PartitionKey} = '{SearchParameterStatusWrapper.SearchParameterStatusPartitionKey}'"),
                    new QueryRequestOptions {
                PartitionKey = partitionKey
            }));

            var results = await query.ExecuteNextAsync();

            if (!results.Any())
            {
                var statuses = await _filebasedRegistry.GetSearchParameterStatuses();

                foreach (var batch in statuses.TakeBatch(100))
                {
                    TransactionalBatch transaction = collection.CreateTransactionalBatch(partitionKey);

                    foreach (SearchParameterStatusWrapper status in batch.Select(x => x.ToSearchParameterStatusWrapper()))
                    {
                        transaction.CreateItem(status);
                    }

                    await transaction.ExecuteAsync();
                }
            }
        }
예제 #6
0
        internal static async Task ExecuteOperationsAsync <TOperation>(this TransactionalBatch transactionalBatch, Dictionary <int, TOperation> operationMappings, PartitionKeyPath partitionKeyPath, CancellationToken cancellationToken = default)
            where TOperation : IOperation
        {
            foreach (var operation in operationMappings.Values)
            {
                operation.Apply(transactionalBatch, partitionKeyPath);
            }

            using (var batchOutcomeResponse = await transactionalBatch.ExecuteAsync(cancellationToken).ConfigureAwait(false))
            {
                for (var i = 0; i < batchOutcomeResponse.Count; i++)
                {
                    var result = batchOutcomeResponse[i];

                    operationMappings.TryGetValue(i, out var operation);
                    IOperation operationToBeExecuted = operation ?? ThrowOnConflictOperation.Instance;

                    if (result.IsSuccessStatusCode)
                    {
                        operationToBeExecuted.Success(result);
                        continue;
                    }

                    // guaranteed to throw
                    operationToBeExecuted.Conflict(result);
                }
            }
        }
예제 #7
0
        /// <inheritdoc />
        public async ValueTask UpdateAsBatchAsync(
            IEnumerable <TItem> items,
            CancellationToken cancellationToken = default)
        {
            List <TItem> list = items.ToList();

            string partitionKey = GetPartitionKeyValue(list);

            Container container = await _containerProvider.GetContainerAsync();

            TransactionalBatch batch = container.CreateTransactionalBatch(new PartitionKey(partitionKey));

            foreach (TItem item in list)
            {
                TransactionalBatchItemRequestOptions options = new();

                if (item is IItemWithEtag itemWithEtag)
                {
                    options.IfMatchEtag = itemWithEtag.Etag;
                }

                batch.UpsertItem(item, options);
            }

            using TransactionalBatchResponse response = await batch.ExecuteAsync(cancellationToken);

            if (!response.IsSuccessStatusCode)
            {
                throw new BatchOperationException <TItem>(response);
            }
        }
        public async Task TestDispose()
        {
            CosmosClient       cosmosClient = new CosmosClient(ConnectionString);
            Database           database     = cosmosClient.GetDatabase("asdf");
            Container          container    = cosmosClient.GetContainer("asdf", "asdf");
            TransactionalBatch batch        = container.CreateTransactionalBatch(new PartitionKey("asdf"));

            batch.ReadItem("Test");

            FeedIterator <dynamic> feedIterator1 = container.GetItemQueryIterator <dynamic>();
            FeedIterator <dynamic> feedIterator2 = container.GetItemQueryIterator <dynamic>(queryText: "select * from T");
            FeedIterator <dynamic> feedIterator3 = database.GetContainerQueryIterator <dynamic>(queryText: "select * from T");

            string userAgent = cosmosClient.ClientContext.UserAgent;

            // Dispose should be idempotent
            cosmosClient.Dispose();
            cosmosClient.Dispose();

            List <Func <Task> > validateAsync = new List <Func <Task> >()
            {
                () => cosmosClient.ReadAccountAsync(),
                () => cosmosClient.CreateDatabaseAsync("asdf"),
                () => database.CreateContainerAsync("asdf", "/pkpathasdf", 200),
                () => container.ReadItemAsync <dynamic>("asdf", new PartitionKey("test")),
                () => container.Scripts.ReadStoredProcedureAsync("asdf"),
                () => container.Scripts.ReadTriggerAsync("asdf"),
                () => container.Scripts.ReadUserDefinedFunctionAsync("asdf"),
                () => batch.ExecuteAsync(),
                () => feedIterator1.ReadNextAsync(),
                () => feedIterator2.ReadNextAsync(),
                () => feedIterator3.ReadNextAsync(),
            };

            foreach (Func <Task> asyncFunc in validateAsync)
            {
                try
                {
                    await asyncFunc();

                    Assert.Fail("Should throw ObjectDisposedException");
                }
                catch (CosmosObjectDisposedException e)
                {
                    string expectedMessage = $"Cannot access a disposed 'CosmosClient'. Follow best practices and use the CosmosClient as a singleton." +
                                             $" CosmosClient was disposed at: {cosmosClient.DisposedDateTimeUtc.Value.ToString("o", CultureInfo.InvariantCulture)}; CosmosClient Endpoint: https://localtestcosmos.documents.azure.com/; Created at: {cosmosClient.ClientConfigurationTraceDatum.ClientCreatedDateTimeUtc.ToString("o", CultureInfo.InvariantCulture)}; UserAgent: {userAgent};";
                    Assert.IsTrue(e.Message.Contains(expectedMessage));
                    string diagnostics = e.Diagnostics.ToString();
                    Assert.IsNotNull(diagnostics);
                    Assert.IsFalse(diagnostics.Contains("NoOp"));
                    Assert.IsTrue(diagnostics.Contains("Client Configuration"));
                    string exceptionString = e.ToString();
                    Assert.IsTrue(exceptionString.Contains(diagnostics));
                    Assert.IsTrue(exceptionString.Contains(e.Message));
                    Assert.IsTrue(exceptionString.Contains(e.StackTrace));
                }
            }
        }
        public async Task TestDispose()
        {
            CosmosClient       cosmosClient = new CosmosClient(ConnectionString);
            Database           database     = cosmosClient.GetDatabase("asdf");
            Container          container    = cosmosClient.GetContainer("asdf", "asdf");
            TransactionalBatch batch        = container.CreateTransactionalBatch(new PartitionKey("asdf"));

            batch.ReadItem("Test");

            // Dispose should be idempotent
            cosmosClient.Dispose();
            cosmosClient.Dispose();

            List <Func <Task> > validateAsync = new List <Func <Task> >()
            {
                () => cosmosClient.ReadAccountAsync(),
                () => cosmosClient.CreateDatabaseAsync("asdf"),
                () => database.CreateContainerAsync("asdf", "/pkpathasdf", 200),
                () => container.ReadItemAsync <dynamic>("asdf", new PartitionKey("test")),
                () => container.Scripts.ReadStoredProcedureAsync("asdf"),
                () => container.Scripts.ReadTriggerAsync("asdf"),
                () => container.Scripts.ReadUserDefinedFunctionAsync("asdf"),
                () => batch.ExecuteAsync(),
                () => container.GetItemQueryIterator <dynamic>(queryText: "select * from T").ReadNextAsync(),
                () => container.GetItemQueryIterator <dynamic>().ReadNextAsync(),
            };

            foreach (Func <Task> asyncFunc in validateAsync)
            {
                try
                {
                    await asyncFunc();

                    Assert.Fail("Should throw ObjectDisposedException");
                }
                catch (ObjectDisposedException) { }
            }
        }
        public async Task ExecuteAsync(Container container, CancellationToken cancellationToken)
        {
            EnsureArg.IsNotNull(container, nameof(container));

            // Detect if registry has been initialized
            var partitionKey = new PartitionKey(SearchParameterStatusWrapper.SearchParameterStatusPartitionKey);
            var query        = _queryFactory.Create <dynamic>(
                container,
                new CosmosQueryContext(
                    new QueryDefinition($"SELECT TOP 1 * FROM c where c.{KnownDocumentProperties.PartitionKey} = '{SearchParameterStatusWrapper.SearchParameterStatusPartitionKey}'"),
                    new QueryRequestOptions {
                PartitionKey = partitionKey
            }));

            var results = await query.ExecuteNextAsync(cancellationToken);

            if (!results.Any())
            {
                var statuses = await _filebasedSearchParameterStatusDataStore.GetSearchParameterStatuses(cancellationToken);

                foreach (var status in statuses.Where(x => _configuration.InitialSortParameterUris.Contains(x.Uri.OriginalString)))
                {
                    status.SortStatus = SortParameterStatus.Enabled;
                }

                foreach (var batch in statuses.TakeBatch(100))
                {
                    TransactionalBatch transaction = container.CreateTransactionalBatch(partitionKey);

                    foreach (SearchParameterStatusWrapper status in batch.Select(x => x.ToSearchParameterStatusWrapper()))
                    {
                        transaction.CreateItem(status);
                    }

                    await transaction.ExecuteAsync(cancellationToken);
                }
            }
        }
예제 #11
0
        public async Task UpsertStatuses(IReadOnlyCollection <ResourceSearchParameterStatus> statuses)
        {
            EnsureArg.IsNotNull(statuses, nameof(statuses));

            if (statuses.Count == 0)
            {
                return;
            }

            foreach (IEnumerable <ResourceSearchParameterStatus> statusBatch in statuses.TakeBatch(100))
            {
                using IScoped <Container> clientScope = _containerScopeFactory.Invoke();
                TransactionalBatch batch = clientScope.Value.CreateTransactionalBatch(new PartitionKey(SearchParameterStatusWrapper.SearchParameterStatusPartitionKey));

                foreach (SearchParameterStatusWrapper status in statusBatch.Select(x => x.ToSearchParameterStatusWrapper()))
                {
                    status.LastUpdated = Clock.UtcNow;
                    batch.UpsertItem(status);
                }

                await batch.ExecuteAsync();
            }
        }
예제 #12
0
        internal static async Task ExecuteOperationAsync(this TransactionalBatch transactionalBatch, IOperation operation, PartitionKeyPath partitionKeyPath, CancellationToken cancellationToken = default)
        {
            operation.Apply(transactionalBatch, partitionKeyPath);

            using (var batchOutcomeResponse = await transactionalBatch.ExecuteAsync(cancellationToken).ConfigureAwait(false))
            {
                if (batchOutcomeResponse.Count > 1)
                {
                    throw new Exception($"The transactional batch was expected to have a single operation but contained {batchOutcomeResponse.Count} operations.");
                }

                var result = batchOutcomeResponse[0];

                if (result.IsSuccessStatusCode)
                {
                    operation.Success(result);
                    return;
                }

                // guaranteed to throw
                operation.Conflict(result);
            }
        }
예제 #13
0
        async Task CreateOrUpdateInBatch(TransactionalBatch batch)
        {
            if (etag == null)
            {
                batch.CreateItemStream(ToStream(value));
            }
            else
            {
                var options = new TransactionalBatchItemRequestOptions
                {
                    IfMatchEtag = etag
                };
                batch.ReplaceItemStream(TransactionEntityId, ToStream(value), options);
            }

            var response = await batch.ExecuteAsync().ConfigureAwait(false);

            if (!response.IsSuccessStatusCode)
            {
                throw new Exception(response.ToString());
            }
            etag = response.Last().ETag;
        }
        public async Task BatchOperationDiagnostic()
        {
            string             pkValue = "DiagnosticTestPk";
            TransactionalBatch batch   = this.Container.CreateTransactionalBatch(new PartitionKey(pkValue));

            List <ToDoActivity> createItems = new List <ToDoActivity>();

            for (int i = 0; i < 50; i++)
            {
                ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(pk: pkValue);
                createItems.Add(item);
                batch.CreateItem <ToDoActivity>(item);
            }

            for (int i = 0; i < 20; i++)
            {
                batch.ReadItem(createItems[i].id);
            }

            TransactionalBatchResponse response = await batch.ExecuteAsync();

            Assert.IsNotNull(response);
            CosmosDiagnosticsTests.VerifyPointDiagnostics(response.Diagnostics);
        }
예제 #15
0
        public async ValueTask DeleteAsBatchAsync(
            IEnumerable <TItem> items,
            CancellationToken cancellationToken = default)
        {
            List <TItem> list = items.ToList();

            string partitionKey = GetPartitionKeyValue(list);

            Container container = await _containerProvider.GetContainerAsync();

            TransactionalBatch batch = container.CreateTransactionalBatch(new PartitionKey(partitionKey));

            foreach (TItem item in list)
            {
                batch.DeleteItem(item.Id);
            }

            using TransactionalBatchResponse response = await batch.ExecuteAsync(cancellationToken);

            if (!response.IsSuccessStatusCode)
            {
                throw new BatchOperationException <TItem>(response);
            }
        }