public void ValidateSetItemRequestOptions() { ItemRequestOptions options = new ItemRequestOptions { PreTriggers = new List <string>() { "preTrigger" }, PostTriggers = new List <string>() { "postTrigger" } }; RequestMessage httpRequest = new RequestMessage( HttpMethod.Post, new Uri("/dbs/testdb/colls/testcontainer/docs/testId", UriKind.Relative)); options.PopulateRequestOptions(httpRequest); Assert.IsTrue(httpRequest.Headers.TryGetValue(HttpConstants.HttpHeaders.PreTriggerInclude, out string preTriggerHeader)); Assert.IsTrue(httpRequest.Headers.TryGetValue(HttpConstants.HttpHeaders.PostTriggerInclude, out string postTriggerHeader)); }
public async Task AllowBatchingRequestsSendsToExecutor_ReplaceStream() { (ContainerInternal container, Mock <BatchAsyncContainerExecutor> mockedExecutor) = this.CreateMockBulkCosmosClientContext(); dynamic testItem = new { id = Guid.NewGuid().ToString(), pk = "FF627B77-568E-4541-A47E-041EAC10E46F", }; using (Stream itemStream = MockCosmosUtil.Serializer.ToStream <dynamic>(testItem)) { ItemRequestOptions itemRequestOptions = new ItemRequestOptions(); Cosmos.PartitionKey partitionKey = new Cosmos.PartitionKey(testItem.pk); using (ResponseMessage streamResponse = await container.ReplaceItemStreamAsync( partitionKey: partitionKey, id: testItem.id, streamPayload: itemStream)) { mockedExecutor.Verify(c => c.AddAsync(It.IsAny <ItemBatchOperation>(), It.IsAny <ITrace>(), It.IsAny <ItemRequestOptions>(), It.IsAny <CancellationToken>()), Times.Once); } } }
public async Task AllowBatchingRequestsSendsToExecutor_ReadStream() { ClientContextCore clientContextCore = new ClientContextCore( MockCosmosUtil.CreateMockCosmosClient(), new CosmosClientOptions() { AllowBulkExecution = true }, new CosmosJsonDotNetSerializer(), new CosmosJsonDotNetSerializer(), new CosmosJsonDotNetSerializer(), null, null, new MockDocumentClient() ); DatabaseCore db = new DatabaseCore(clientContextCore, "test"); ExecutorContainerCore container = new ExecutorContainerCore(clientContextCore, db, "test"); dynamic testItem = new { id = Guid.NewGuid().ToString(), pk = "FF627B77-568E-4541-A47E-041EAC10E46F", }; using (Stream itemStream = MockCosmosUtil.Serializer.ToStream <dynamic>(testItem)) { ItemRequestOptions itemRequestOptions = new ItemRequestOptions(); Cosmos.PartitionKey partitionKey = new Cosmos.PartitionKey(testItem.pk); using (ResponseMessage streamResponse = await container.ReadItemStreamAsync( partitionKey: partitionKey, id: testItem.id)) { container.MockedExecutor.Verify(c => c.AddAsync(It.IsAny <ItemBatchOperation>(), It.IsAny <ItemRequestOptions>(), It.IsAny <CancellationToken>()), Times.Once); } } }
public async override Task <ItemResponse <T> > UpsertItemAsync <T>( T item, PartitionKey?partitionKey = null, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default) { if (item == null) { throw new ArgumentNullException(nameof(item)); } if (requestOptions is EncryptionItemRequestOptions encryptionItemRequestOptions) { if (partitionKey == null) { throw new NotSupportedException($"{nameof(partitionKey)} cannot be null for operations using {nameof(EncryptionContainer)}."); } using (Stream itemStream = this.cosmosSerializer.ToStream <T>(item)) { using (ResponseMessage responseMessage = await this.UpsertItemStreamAsync(itemStream, partitionKey.Value, requestOptions, cancellationToken)) { return(this.responseFactory.CreateItemResponse <T>(responseMessage)); } } } else { return(await this.container.UpsertItemAsync(item, partitionKey, requestOptions, cancellationToken)); } }
private async Task <DocumentServiceLease> TryReplaceLeaseAsync( DocumentServiceLease lease, PartitionKey partitionKey, string itemId) { try { ItemRequestOptions itemRequestOptions = this.CreateIfMatchOptions(lease); ItemResponse <DocumentServiceLease> response = await this.container.TryReplaceItemAsync <DocumentServiceLease>( itemId, lease, partitionKey, itemRequestOptions).ConfigureAwait(false); return(response.Resource); } catch (CosmosException ex) { DefaultTrace.TraceWarning("Lease operation exception, status code: {0}", ex.StatusCode); if (ex.StatusCode == HttpStatusCode.NotFound) { throw new LeaseLostException(lease, true); } if (ex.StatusCode == HttpStatusCode.PreconditionFailed) { return(null); } if (ex.StatusCode == HttpStatusCode.Conflict) { throw new LeaseLostException(lease, ex, false); } throw; } }
public async Task VerifyRequestOptionCustomRequestHeaders() { CustomHeaderValidationHandler headerValidationHandler = new CustomHeaderValidationHandler(); using CosmosClient client = TestCommon.CreateCosmosClient(x => x.AddCustomHandlers(headerValidationHandler)); Database database = null; try { database = await client.CreateDatabaseAsync(nameof(VerifyRequestOptionCustomRequestHeaders) + Guid.NewGuid().ToString()); Container container = await database.CreateContainerAsync( Guid.NewGuid().ToString(), "/pk"); ToDoActivity toDoActivity = ToDoActivity.CreateRandomToDoActivity(); ItemRequestOptions requestOptions = new ItemRequestOptions { AddRequestHeaders = (headers) => headers["x-ms-cosmos-database-rid"] = "databaseRidValue", }; await container.CreateItemAsync(toDoActivity, new PartitionKey(toDoActivity.pk), requestOptions : requestOptions); // null pass requestOptions.AddRequestHeaders = null; await container.ReadItemAsync <ToDoActivity>(toDoActivity.id, new PartitionKey(toDoActivity.pk), requestOptions : requestOptions); } finally { if (database != null) { await database.DeleteStreamAsync(); } } }
public override async Task <ItemResponse <T> > ReplaceItemAsync <T>( T item, string id, PartitionKey?partitionKey = null, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default) { if (id == null) { throw new ArgumentNullException(nameof(id)); } if (item == null) { throw new ArgumentNullException(nameof(item)); } if (partitionKey == null) { throw new NotSupportedException($"{nameof(partitionKey)} cannot be null for operations using {nameof(EncryptionContainer)}."); } ResponseMessage responseMessage; using (Stream itemStream = this.CosmosSerializer.ToStream <T>(item)) { responseMessage = await this.ReplaceItemHelperAsync( itemStream, id, partitionKey.Value, requestOptions, cancellationToken); } return(this.ResponseFactory.CreateItemResponse <T>(responseMessage)); }
public override async Task <ResponseMessage> ReplaceItemStreamAsync( Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default) { if (id == null) { throw new ArgumentNullException(nameof(id)); } if (streamPayload == null) { throw new ArgumentNullException(nameof(streamPayload)); } return(await this.ReplaceItemHelperAsync( streamPayload, id, partitionKey, requestOptions, cancellationToken)); }
public override async Task <ResponseMessage> UpsertItemStreamAsync( Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default) { if (streamPayload == null) { throw new ArgumentNullException(nameof(streamPayload)); } CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions); using (diagnosticsContext.CreateScope("UpsertItemStream")) { return(await this.UpsertItemHelperAsync( streamPayload, partitionKey, requestOptions, decryptResponse : true, diagnosticsContext, cancellationToken)); } }
private async Task VerifyItemNullExceptions( dynamic testItem, ItemRequestOptions requestOptions = null) { TestHandler testHandler = new TestHandler((request, cancellationToken) => { Assert.Fail("Null partition key should be blocked without the correct request option"); return null; }); CosmosClient client = MockCosmosUtil.CreateMockCosmosClient( (cosmosClientBuilder) => cosmosClientBuilder.AddCustomHandlers(testHandler)); CosmosContainer container = client.Databases["testdb"] .Containers["testcontainer"]; await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => { await container.CreateItemAsync<dynamic>( partitionKey: null, item: testItem, requestOptions: requestOptions); }, "CreateItemAsync should throw ArgumentNullException without the correct request option set."); await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => { await container.ReadItemAsync<dynamic>( partitionKey: null, id: testItem.id, requestOptions: requestOptions); }, "ReadItemAsync should throw ArgumentNullException without the correct request option set."); await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => { await container.UpsertItemAsync<dynamic>( partitionKey: null, item: testItem, requestOptions: requestOptions); }, "UpsertItemAsync should throw ArgumentNullException without the correct request option set."); await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => { await container.ReplaceItemAsync<dynamic>( partitionKey: null, id: testItem.id, item: testItem, requestOptions: requestOptions); }, "ReplaceItemAsync should throw ArgumentNullException without the correct request option set."); await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => { await container.DeleteItemAsync<dynamic>( partitionKey: null, id: testItem.id, requestOptions: requestOptions); }, "DeleteItemAsync should throw ArgumentNullException without the correct request option set."); CosmosJsonSerializerCore jsonSerializer = new CosmosJsonSerializerCore(); using (Stream itemStream = jsonSerializer.ToStream<dynamic>(testItem)) { await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => { await container.CreateItemAsStreamAsync( partitionKey: null, streamPayload: itemStream, requestOptions: requestOptions); }, "CreateItemAsync should throw ArgumentNullException without the correct request option set."); await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => { await container.ReadItemAsStreamAsync( partitionKey: null, id: testItem.id, requestOptions: requestOptions); }, "ReadItemAsync should throw ArgumentNullException without the correct request option set."); await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => { await container.UpsertItemAsStreamAsync( partitionKey: null, streamPayload: itemStream, requestOptions: requestOptions); }, "UpsertItemAsync should throw ArgumentNullException without the correct request option set."); await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => { await container.ReplaceItemAsStreamAsync( partitionKey: null, id: testItem.id, streamPayload: itemStream, requestOptions: requestOptions); }, "ReplaceItemAsync should throw ArgumentNullException without the correct request option set."); await Assert.ThrowsExceptionAsync<ArgumentNullException>(async () => { await container.DeleteItemAsStreamAsync( partitionKey: null, id: testItem.id, requestOptions: requestOptions); }, "DeleteItemAsync should throw ArgumentNullException without the correct request option set."); } }
/// <summary> /// Generates a data encryption key, wraps it using the key wrap metadata provided /// with the key wrapping provider in the <see cref="CosmosDataEncryptionKeyProvider"/> for encryption, /// and saves the wrapped data encryption key as an asynchronous operation in the Azure Cosmos service. /// </summary> /// <param name="id">Unique identifier for the data encryption key.</param> /// <param name="encryptionAlgorithm">Encryption algorithm that will be used along with this data encryption key to encrypt/decrypt data.</param> /// <param name="encryptionKeyWrapMetadata">Metadata used by the configured key wrapping provider in order to wrap the key.</param> /// <param name="requestOptions">(Optional) The options for the request.</param> /// <param name="cancellationToken">(Optional) Token representing request cancellation.</param> /// <returns>An awaitable response which wraps a <see cref="DataEncryptionKeyProperties"/> containing the read resource record.</returns> /// <exception cref="ArgumentNullException">If <paramref name="id"/> is not set.</exception> /// <exception cref="CosmosException"> /// This exception can encapsulate many different types of errors. /// To determine the specific error always look at the StatusCode property. /// Some common codes you may get when creating a data encryption key are: /// <list type="table"> /// <listheader> /// <term>StatusCode</term><description>Reason for exception</description> /// </listheader> /// <item> /// <term>400</term><description>BadRequest - This means something was wrong with the request supplied. It is likely that an id was not supplied for the new encryption key.</description> /// </item> /// <item> /// <term>409</term><description>Conflict - This means an <see cref="DataEncryptionKeyProperties"/> with an id matching the id you supplied already existed.</description> /// </item> /// </list> /// </exception> /// <example> /// /// <code language="c#"> /// <![CDATA[ /// AzureKeyVaultKeyWrapMetadata wrapMetadata = new AzureKeyVaultKeyWrapMetadata("/path/to/my/akv/secret/v1"); /// await this.cosmosDatabase.CreateDataEncryptionKeyAsync("myKey", wrapMetadata); /// ]]> /// </code> /// </example> public abstract Task <ItemResponse <DataEncryptionKeyProperties> > CreateDataEncryptionKeyAsync( string id, string encryptionAlgorithm, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary> /// Reads the properties of a data encryption key from the Azure Cosmos service as an asynchronous operation. /// </summary> /// <param name="id">Unique identifier of the data encryption key.</param> /// <param name="requestOptions">(Optional) The options for the request.</param> /// <param name="cancellationToken">(Optional) Token representing request cancellation.</param> /// <returns>An awaitable response which wraps a <see cref="DataEncryptionKeyProperties"/> containing details of the data encryption key that was read.</returns> /// <exception cref="CosmosException"> /// This exception can encapsulate many different types of errors. /// To determine the specific error always look at the StatusCode property. /// Some common codes you may get when reading a data encryption key are: /// <list type="table"> /// <listheader> /// <term>StatusCode</term> /// <description>Reason for exception</description> /// </listheader> /// <item> /// <term>404</term> /// <description> /// NotFound - This means the resource or parent resource you tried to read did not exist. /// </description> /// </item> /// <item> /// <term>429</term> /// <description> /// TooManyRequests - This means you have exceeded the number of request units per second. /// Consult the CosmosException.RetryAfter value to see how long you should wait before retrying this operation. /// </description> /// </item> /// </list> /// </exception> /// <example> /// <code language="c#"> /// <![CDATA[ /// DataEncryptionKey key = this.database.GetDataEncryptionKey("keyId"); /// DataEncryptionKeyProperties keyProperties = await key.ReadAsync(); /// ]]> /// </code> /// </example> public abstract Task <ItemResponse <DataEncryptionKeyProperties> > ReadDataEncryptionKeyAsync( string id, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default(CancellationToken));
public override async Task <ItemResponse <DataEncryptionKeyProperties> > CreateDataEncryptionKeyAsync( string id, string encryptionAlgorithm, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default) { if (string.IsNullOrEmpty(id)) { throw new ArgumentNullException(nameof(id)); } if (!CosmosEncryptionAlgorithm.VerifyIfSupportedAlgorithm(encryptionAlgorithm)) { throw new ArgumentException(string.Format("Unsupported Encryption Algorithm {0}", encryptionAlgorithm), nameof(encryptionAlgorithm)); } if (encryptionKeyWrapMetadata == null) { throw new ArgumentNullException(nameof(encryptionKeyWrapMetadata)); } CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions); byte[] wrappedDek = null; EncryptionKeyWrapMetadata updatedMetadata = null; InMemoryRawDek inMemoryRawDek = null; if (string.Equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized)) { (wrappedDek, updatedMetadata, inMemoryRawDek) = await this.GenerateAndWrapRawDekForLegacyEncAlgoAsync( id, encryptionAlgorithm, encryptionKeyWrapMetadata, diagnosticsContext, cancellationToken); } else if (string.Equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized)) { (wrappedDek, updatedMetadata) = this.GenerateAndWrapPdekForMdeEncAlgo(encryptionKeyWrapMetadata); } DataEncryptionKeyProperties dekProperties = new DataEncryptionKeyProperties( id, encryptionAlgorithm, wrappedDek, updatedMetadata, DateTime.UtcNow); ItemResponse <DataEncryptionKeyProperties> dekResponse = await this.DekProvider.Container.CreateItemAsync( dekProperties, new PartitionKey(dekProperties.Id), cancellationToken : cancellationToken); this.DekProvider.DekCache.SetDekProperties(id, dekResponse.Resource); if (string.Equals(encryptionAlgorithm, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized)) { this.DekProvider.DekCache.SetRawDek(id, inMemoryRawDek); } return(dekResponse); }
public async Task UpdateItemAsync(Container container, GeneralModel item, ItemRequestOptions itemRequestOptions = null) { await container.UpsertItemAsync(item, new PartitionKey(item.ID), itemRequestOptions); }
public async Task PointOperationDiagnostic(bool disableDiagnostics) { ItemRequestOptions requestOptions = new ItemRequestOptions(); if (disableDiagnostics) { requestOptions.DiagnosticContextFactory = () => EmptyCosmosDiagnosticsContext.Singleton; } else { // Add 10 seconds to ensure CPU history is recorded await Task.Delay(TimeSpan.FromSeconds(10)); } //Checking point operation diagnostics on typed operations ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity(); ItemResponse <ToDoActivity> createResponse = await this.Container.CreateItemAsync <ToDoActivity>( item : testItem, requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( createResponse.Diagnostics, disableDiagnostics); ItemResponse <ToDoActivity> readResponse = await this.Container.ReadItemAsync <ToDoActivity>( id : testItem.id, partitionKey : new PartitionKey(testItem.status), requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( readResponse.Diagnostics, disableDiagnostics); testItem.description = "NewDescription"; ItemResponse <ToDoActivity> replaceResponse = await this.Container.ReplaceItemAsync <ToDoActivity>( item : testItem, id : testItem.id, partitionKey : new PartitionKey(testItem.status), requestOptions : requestOptions); Assert.AreEqual(replaceResponse.Resource.description, "NewDescription"); CosmosDiagnosticsTests.VerifyPointDiagnostics( replaceResponse.Diagnostics, disableDiagnostics); testItem.description = "PatchedDescription"; ContainerInternal containerInternal = (ContainerInternal)this.Container; List <PatchOperation> patch = new List <PatchOperation>() { PatchOperation.Replace("/description", testItem.description) }; ItemResponse <ToDoActivity> patchResponse = await containerInternal.PatchItemAsync <ToDoActivity>( id : testItem.id, partitionKey : new PartitionKey(testItem.status), patchOperations : patch, requestOptions : requestOptions); Assert.AreEqual(patchResponse.Resource.description, "PatchedDescription"); CosmosDiagnosticsTests.VerifyPointDiagnostics( patchResponse.Diagnostics, disableDiagnostics); ItemResponse <ToDoActivity> deleteResponse = await this.Container.DeleteItemAsync <ToDoActivity>( partitionKey : new Cosmos.PartitionKey(testItem.status), id : testItem.id, requestOptions : requestOptions); Assert.IsNotNull(deleteResponse); CosmosDiagnosticsTests.VerifyPointDiagnostics( deleteResponse.Diagnostics, disableDiagnostics); //Checking point operation diagnostics on stream operations ResponseMessage createStreamResponse = await this.Container.CreateItemStreamAsync( partitionKey : new PartitionKey(testItem.status), streamPayload : TestCommon.SerializerCore.ToStream <ToDoActivity>(testItem), requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( createStreamResponse.Diagnostics, disableDiagnostics); ResponseMessage readStreamResponse = await this.Container.ReadItemStreamAsync( id : testItem.id, partitionKey : new PartitionKey(testItem.status), requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( readStreamResponse.Diagnostics, disableDiagnostics); ResponseMessage replaceStreamResponse = await this.Container.ReplaceItemStreamAsync( streamPayload : TestCommon.SerializerCore.ToStream <ToDoActivity>(testItem), id : testItem.id, partitionKey : new PartitionKey(testItem.status), requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( replaceStreamResponse.Diagnostics, disableDiagnostics); ResponseMessage patchStreamResponse = await containerInternal.PatchItemStreamAsync( id : testItem.id, partitionKey : new PartitionKey(testItem.status), patchOperations : patch, requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( patchStreamResponse.Diagnostics, disableDiagnostics); ResponseMessage deleteStreamResponse = await this.Container.DeleteItemStreamAsync( id : testItem.id, partitionKey : new PartitionKey(testItem.status), requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( deleteStreamResponse.Diagnostics, disableDiagnostics); // Ensure diagnostics are set even on failed operations testItem.description = new string('x', Microsoft.Azure.Documents.Constants.MaxResourceSizeInBytes + 1); ResponseMessage createTooBigStreamResponse = await this.Container.CreateItemStreamAsync( partitionKey : new PartitionKey(testItem.status), streamPayload : TestCommon.SerializerCore.ToStream <ToDoActivity>(testItem), requestOptions : requestOptions); Assert.IsFalse(createTooBigStreamResponse.IsSuccessStatusCode); CosmosDiagnosticsTests.VerifyPointDiagnostics( createTooBigStreamResponse.Diagnostics, disableDiagnostics); }
/// <summary> /// Creates a new instance of the <see cref="CosmosDbArgs"/> class with the <paramref name="containerId"/> and <paramref name="requestOptions"/>. /// </summary> /// <param name="containerId">The <see cref="Container"/> identifier.</param> /// <param name="partitionKey">The optional <see cref="PartitionKey"/>.</param> /// <param name="requestOptions">The optional <see cref="T:ItemRequestOptions"/>.</param> /// <returns>The <see cref="CosmosDbArgs"/>.</returns> public static CosmosDbArgs Create(string containerId, PartitionKey partitionKey, ItemRequestOptions requestOptions = null) { return(new CosmosDbArgs(containerId, partitionKey, requestOptions)); }
private static Task <ResponseMessage> ExecuteCreateStreamAsync(Container container, ToDoActivity item, ItemRequestOptions itemRequestOptions = null) { return(container.CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(item), new PartitionKey(item.pk), itemRequestOptions)); }
public override async Task <ItemResponse <T> > CreateItemAsync <T>( T item, PartitionKey?partitionKey = null, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default) { if (item == null) { throw new ArgumentNullException(nameof(item)); } if (!(requestOptions is EncryptionItemRequestOptions encryptionItemRequestOptions) || encryptionItemRequestOptions.EncryptionOptions == null) { return(await this.container.CreateItemAsync <T>( item, partitionKey, requestOptions, cancellationToken)); } if (partitionKey == null) { throw new NotSupportedException($"{nameof(partitionKey)} cannot be null for operations using {nameof(EncryptionContainer)}."); } CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions); using (diagnosticsContext.CreateScope("CreateItem")) { ResponseMessage responseMessage; if (item is EncryptableItem encryptableItem) { using (Stream streamPayload = encryptableItem.ToStream(this.CosmosSerializer)) { responseMessage = await this.CreateItemHelperAsync( streamPayload, partitionKey.Value, requestOptions, decryptResponse : false, diagnosticsContext, cancellationToken); } encryptableItem.SetDecryptableItem( EncryptionProcessor.BaseSerializer.FromStream <JObject>(responseMessage.Content), this.Encryptor, this.CosmosSerializer); return(new EncryptionItemResponse <T>( responseMessage, item)); } else { using (Stream itemStream = this.CosmosSerializer.ToStream <T>(item)) { responseMessage = await this.CreateItemHelperAsync( itemStream, partitionKey.Value, requestOptions, decryptResponse : true, diagnosticsContext, cancellationToken); } return(this.ResponseFactory.CreateItemResponse <T>(responseMessage)); } } }
private async Task ValidateItemStream( ItemRequestOptions requestOptions, Action <ResponseMessage> ValidateWrite, Action <ResponseMessage> ValidateRead) { ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(); using (ResponseMessage responseMessage = await this.container.CreateItemStreamAsync( TestCommon.SerializerCore.ToStream(item), new PartitionKey(item.status), requestOptions: requestOptions)) { Assert.AreEqual(HttpStatusCode.Created, responseMessage.StatusCode); ValidateWrite(responseMessage); } using (ResponseMessage responseMessage = await this.container.ReadItemStreamAsync( item.id, new PartitionKey(item.status), requestOptions: requestOptions)) { Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); ValidateRead(responseMessage); } item.cost = 424242.42; using (ResponseMessage responseMessage = await this.container.UpsertItemStreamAsync( TestCommon.SerializerCore.ToStream(item), new PartitionKey(item.status), requestOptions: requestOptions)) { Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); ValidateWrite(responseMessage); } item.cost = 9000.42; using (ResponseMessage responseMessage = await this.container.ReplaceItemStreamAsync( TestCommon.SerializerCore.ToStream(item), item.id, new PartitionKey(item.status), requestOptions: requestOptions)) { Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); ValidateWrite(responseMessage); } item.cost = 1000; List <PatchOperation> patch = new List <PatchOperation>() { PatchOperation.CreateReplaceOperation("/cost", item.cost) }; using (ResponseMessage responseMessage = await this.containerInternal.PatchItemStreamAsync( item.id, new PartitionKey(item.status), patchOperations: patch, requestOptions: requestOptions)) { Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); ValidateWrite(responseMessage); } using (ResponseMessage responseMessage = await this.container.DeleteItemStreamAsync( item.id, new PartitionKey(item.status), requestOptions: requestOptions)) { Assert.AreEqual(HttpStatusCode.NoContent, responseMessage.StatusCode); this.ValidateItemStreamNoContentResponse(responseMessage); } }
private async Task<ItemResponse<DocumentEntity<T>>> CreateDocumentInternalAsync<T>(T entity, ItemRequestOptions requestOptions = null) where T : IIdentifiable { DocumentEntity<T> doc = CreateDocumentEntity(entity); return await RepositoryContainer.CreateItemAsync(doc, requestOptions: requestOptions); }
public async Task AddItemsAsync<T>(Container container, T item, string partitionKey, ItemRequestOptions itemRequestOptions = null) { var partitionKeyStruct = new PartitionKey(partitionKey); await container.CreateItemAsync<T>(item, partitionKeyStruct, itemRequestOptions); }
public async Task CrossPartitionBiDirectionalItemReadFeedTest(bool useStatelessIteration) { //create items const int total = 30; const int maxItemCount = 10; List <string> items = new List <string>(); for (int i = 0; i < total; i++) { string item = $@" {{ ""id"": ""{i}"" }}"; using (ResponseMessage createResponse = await this.Container.CreateItemStreamAsync( CosmosReadFeedTests.GenerateStreamFromString(item), new Cosmos.PartitionKey(i.ToString()))) { Assert.IsTrue(createResponse.IsSuccessStatusCode); } } string lastKnownContinuationToken = null; FeedIterator iter = this.Container.Database.GetContainer(this.Container.Id) .GetItemStreamIterator(maxItemCount, continuationToken: lastKnownContinuationToken); int count = 0; List <string> forwardOrder = new List <string>(); while (iter.HasMoreResults) { if (useStatelessIteration) { iter = this.Container.Database.GetContainer(this.Container.Id) .GetItemStreamIterator(maxItemCount, continuationToken: lastKnownContinuationToken); } using (ResponseMessage response = await iter.ReadNextAsync()) { lastKnownContinuationToken = response.Headers.Continuation; Assert.IsNotNull(response); using (StreamReader reader = new StreamReader(response.Content)) { string json = await reader.ReadToEndAsync(); JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); count += documents.Count; if (documents.Any()) { forwardOrder.Add(documents.First().SelectToken("id").ToString()); } } } } Assert.IsNull(lastKnownContinuationToken); Assert.IsNotNull(forwardOrder); Assert.AreEqual(total, count); Assert.IsFalse(forwardOrder.Where(x => string.IsNullOrEmpty(x)).Any()); ItemRequestOptions requestOptions = new ItemRequestOptions(); requestOptions.Properties = requestOptions.Properties = new Dictionary <string, object>(); requestOptions.Properties.Add(HttpConstants.HttpHeaders.EnumerationDirection, (byte)BinaryScanDirection.Reverse); count = 0; List <string> reverseOrder = new List <string>(); lastKnownContinuationToken = null; iter = this.Container.Database.GetContainer(this.Container.Id) .GetItemStreamIterator(maxItemCount, continuationToken: lastKnownContinuationToken, requestOptions: requestOptions); while (iter.HasMoreResults) { if (useStatelessIteration) { iter = this.Container.Database.GetContainer(this.Container.Id) .GetItemStreamIterator(maxItemCount, continuationToken: lastKnownContinuationToken, requestOptions: requestOptions); } using (ResponseMessage response = await iter.ReadNextAsync()) { lastKnownContinuationToken = response.Headers.Continuation; Assert.IsNotNull(response); using (StreamReader reader = new StreamReader(response.Content)) { string json = await reader.ReadToEndAsync(); JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); count += documents.Count; if (documents.Any()) { reverseOrder.Add(documents.First().SelectToken("id").ToString()); } } } } Assert.IsNull(lastKnownContinuationToken); Assert.IsNotNull(reverseOrder); Assert.AreEqual(total, count); forwardOrder.Reverse(); CollectionAssert.AreEqual(forwardOrder, reverseOrder); Assert.IsFalse(reverseOrder.Where(x => string.IsNullOrEmpty(x)).Any()); }
/// <summary> /// Initializes a new instance of the <see cref="CosmosDbArgs"/> class. /// </summary> /// <param name="containerId">The <see cref="Container"/> identifier.</param> /// <param name="partitionKey">The optional <see cref="PartitionKey"/>.</param> /// <param name="requestOptions">The optional <see cref="T:ItemRequestOptions"/>.</param> public CosmosDbArgs(string containerId, PartitionKey partitionKey, ItemRequestOptions requestOptions = null) { ContainerId = Check.NotEmpty(containerId, nameof(containerId)); PartitionKey = partitionKey; ItemRequestOptions = requestOptions; }
public async Task PointOperationDiagnostic(bool disableDiagnostics) { ItemRequestOptions requestOptions = new ItemRequestOptions(); if (disableDiagnostics) { requestOptions.DiagnosticContextFactory = () => EmptyCosmosDiagnosticsContext.Singleton; } ; //Checking point operation diagnostics on typed operations ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity(); ItemResponse <ToDoActivity> createResponse = await this.Container.CreateItemAsync <ToDoActivity>( item : testItem, requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( createResponse.Diagnostics, disableDiagnostics); ItemResponse <ToDoActivity> readResponse = await this.Container.ReadItemAsync <ToDoActivity>( id : testItem.id, partitionKey : new PartitionKey(testItem.status), requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( readResponse.Diagnostics, disableDiagnostics); testItem.description = "NewDescription"; ItemResponse <ToDoActivity> replaceResponse = await this.Container.ReplaceItemAsync <ToDoActivity>( item : testItem, id : testItem.id, partitionKey : new PartitionKey(testItem.status), requestOptions : requestOptions); Assert.AreEqual(replaceResponse.Resource.description, "NewDescription"); CosmosDiagnosticsTests.VerifyPointDiagnostics( replaceResponse.Diagnostics, disableDiagnostics); ItemResponse <ToDoActivity> deleteResponse = await this.Container.DeleteItemAsync <ToDoActivity>( partitionKey : new Cosmos.PartitionKey(testItem.status), id : testItem.id, requestOptions : requestOptions); Assert.IsNotNull(deleteResponse); CosmosDiagnosticsTests.VerifyPointDiagnostics( deleteResponse.Diagnostics, disableDiagnostics); //Checking point operation diagnostics on stream operations ResponseMessage createStreamResponse = await this.Container.CreateItemStreamAsync( partitionKey : new PartitionKey(testItem.status), streamPayload : TestCommon.SerializerCore.ToStream <ToDoActivity>(testItem), requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( createStreamResponse.Diagnostics, disableDiagnostics); ResponseMessage readStreamResponse = await this.Container.ReadItemStreamAsync( id : testItem.id, partitionKey : new PartitionKey(testItem.status), requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( readStreamResponse.Diagnostics, disableDiagnostics); ResponseMessage replaceStreamResponse = await this.Container.ReplaceItemStreamAsync( streamPayload : TestCommon.SerializerCore.ToStream <ToDoActivity>(testItem), id : testItem.id, partitionKey : new PartitionKey(testItem.status), requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( replaceStreamResponse.Diagnostics, disableDiagnostics); ResponseMessage deleteStreamResponse = await this.Container.DeleteItemStreamAsync( id : testItem.id, partitionKey : new PartitionKey(testItem.status), requestOptions : requestOptions); CosmosDiagnosticsTests.VerifyPointDiagnostics( deleteStreamResponse.Diagnostics, disableDiagnostics); // Ensure diagnostics are set even on failed operations testItem.description = new string('x', Microsoft.Azure.Documents.Constants.MaxResourceSizeInBytes + 1); ResponseMessage createTooBigStreamResponse = await this.Container.CreateItemStreamAsync( partitionKey : new PartitionKey(testItem.status), streamPayload : TestCommon.SerializerCore.ToStream <ToDoActivity>(testItem), requestOptions : requestOptions); Assert.IsFalse(createTooBigStreamResponse.IsSuccessStatusCode); CosmosDiagnosticsTests.VerifyPointDiagnostics( createTooBigStreamResponse.Diagnostics, disableDiagnostics); }
public async Task PointOperationThrottledDiagnostic(bool disableDiagnostics) { string errorMessage = "Mock throttle exception" + Guid.NewGuid().ToString(); Guid exceptionActivityId = Guid.NewGuid(); // Set a small retry count to reduce test time CosmosClient throttleClient = TestCommon.CreateCosmosClient(builder => builder.WithThrottlingRetryOptions(TimeSpan.FromSeconds(5), 5) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, (uri, resourceOperation, request) => TransportClientHelper.ReturnThrottledStoreResponseOnItemOperation( uri, resourceOperation, request, exceptionActivityId, errorMessage))) ); ItemRequestOptions requestOptions = new ItemRequestOptions(); if (disableDiagnostics) { requestOptions.DiagnosticContextFactory = () => EmptyCosmosDiagnosticsContext.Singleton; } ; Container containerWithThrottleException = throttleClient.GetContainer( this.database.Id, this.Container.Id); //Checking point operation diagnostics on typed operations ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity(); try { ItemResponse <ToDoActivity> createResponse = await containerWithThrottleException.CreateItemAsync <ToDoActivity>( item : testItem, requestOptions : requestOptions); Assert.Fail("Should have thrown a request timeout exception"); } catch (CosmosException ce) when((int)ce.StatusCode == (int)Documents.StatusCodes.TooManyRequests) { string exception = ce.ToString(); Assert.IsNotNull(exception); Assert.IsTrue(exception.Contains(exceptionActivityId.ToString())); Assert.IsTrue(exception.Contains(errorMessage)); string diagnosics = ce.Diagnostics.ToString(); if (disableDiagnostics) { Assert.IsTrue(string.IsNullOrEmpty(diagnosics)); } else { Assert.IsFalse(string.IsNullOrEmpty(diagnosics)); Assert.IsTrue(exception.Contains(diagnosics)); DiagnosticValidator.ValidatePointOperationDiagnostics(ce.DiagnosticsContext); } } }
/// <inheritdoc/> public override async Task <ItemResponse <DataEncryptionKeyProperties> > RewrapDataEncryptionKeyAsync( string id, EncryptionKeyWrapMetadata newWrapMetadata, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default) { if (newWrapMetadata == null) { throw new ArgumentNullException(nameof(newWrapMetadata)); } CosmosDiagnosticsContext diagnosticsContext = CosmosDiagnosticsContext.Create(requestOptions); DataEncryptionKeyProperties dekProperties = await this.FetchDataEncryptionKeyPropertiesAsync( id, diagnosticsContext, cancellationToken); byte[] rawkey = null; if (string.Equals(dekProperties.EncryptionAlgorithm, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized)) { InMemoryRawDek inMemoryRawDek = await this.FetchUnwrappedAsync( dekProperties, diagnosticsContext, cancellationToken); rawkey = inMemoryRawDek.DataEncryptionKey.RawKey; } else if (string.Equals(dekProperties.EncryptionAlgorithm, CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized)) { EncryptionKeyUnwrapResult encryptionKeyUnwrapResult = await this.DekProvider.MdeKeyWrapProvider.UnwrapKeyAsync( dekProperties.WrappedDataEncryptionKey, dekProperties.EncryptionKeyWrapMetadata, cancellationToken); rawkey = encryptionKeyUnwrapResult.DataEncryptionKey; } (byte[] wrappedDek, EncryptionKeyWrapMetadata updatedMetadata, InMemoryRawDek updatedRawDek) = await this.WrapAsync( id, rawkey, dekProperties.EncryptionAlgorithm, newWrapMetadata, diagnosticsContext, cancellationToken); if (requestOptions == null) { requestOptions = new ItemRequestOptions(); } requestOptions.IfMatchEtag = dekProperties.ETag; DataEncryptionKeyProperties newDekProperties = new DataEncryptionKeyProperties(dekProperties) { WrappedDataEncryptionKey = wrappedDek, EncryptionKeyWrapMetadata = updatedMetadata, }; ItemResponse <DataEncryptionKeyProperties> response; try { response = await this.DekProvider.Container.ReplaceItemAsync( newDekProperties, newDekProperties.Id, new PartitionKey(newDekProperties.Id), requestOptions, cancellationToken); Debug.Assert(response.Resource != null); } catch (CosmosException ex) { if (!ex.StatusCode.Equals(HttpStatusCode.PreconditionFailed)) { throw; } // Handle if exception is due to etag mismatch. The scenario is as follows - say there are 2 clients A and B that both have the DEK properties cached. // From A, rewrap worked and the DEK is updated. Now from B, rewrap was attempted later based on the cached properties which will fail due to etag mismatch. // To address this, we do an explicit read, which reads the key from storage and updates the cached properties; and then attempt rewrap again. await this.ReadDataEncryptionKeyAsync( newDekProperties.Id, requestOptions, cancellationToken); return(await this.RewrapDataEncryptionKeyAsync( id, newWrapMetadata, requestOptions, cancellationToken)); } this.DekProvider.DekCache.SetDekProperties(id, response.Resource); if (string.Equals(dekProperties.EncryptionAlgorithm, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized)) { this.DekProvider.DekCache.SetRawDek(id, updatedRawDek); } return(response); }
private async Task VerifyItemOperations( Cosmos.PartitionKey partitionKey, string partitionKeySerialized, dynamic testItem, ItemRequestOptions requestOptions = null) { ResponseMessage response = null; HttpStatusCode httpStatusCode = HttpStatusCode.OK; int testHandlerHitCount = 0; TestHandler testHandler = new TestHandler((request, cancellationToken) => { Assert.IsTrue(request.RequestUri.OriginalString.StartsWith(@"dbs/testdb/colls/testcontainer")); Assert.AreEqual(requestOptions, request.RequestOptions); Assert.AreEqual(ResourceType.Document, request.ResourceType); Assert.IsNotNull(request.Headers.PartitionKey); Assert.AreEqual(partitionKeySerialized, request.Headers.PartitionKey); testHandlerHitCount++; response = new ResponseMessage(httpStatusCode, request, errorMessage: null) { Content = request.Content }; return(Task.FromResult(response)); }); using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient( (builder) => builder.AddCustomHandlers(testHandler)); Container container = client.GetDatabase("testdb") .GetContainer("testcontainer"); ItemResponse <dynamic> itemResponse = await container.CreateItemAsync <dynamic>( item : testItem, requestOptions : requestOptions); Assert.IsNotNull(itemResponse); Assert.AreEqual(httpStatusCode, itemResponse.StatusCode); itemResponse = await container.ReadItemAsync <dynamic>( partitionKey : partitionKey, id : testItem.id, requestOptions : requestOptions); Assert.IsNotNull(itemResponse); Assert.AreEqual(httpStatusCode, itemResponse.StatusCode); itemResponse = await container.UpsertItemAsync <dynamic>( item : testItem, requestOptions : requestOptions); Assert.IsNotNull(itemResponse); Assert.AreEqual(httpStatusCode, itemResponse.StatusCode); itemResponse = await container.ReplaceItemAsync <dynamic>( id : testItem.id, item : testItem, requestOptions : requestOptions); Assert.IsNotNull(itemResponse); Assert.AreEqual(httpStatusCode, itemResponse.StatusCode); itemResponse = await container.DeleteItemAsync <dynamic>( partitionKey : partitionKey, id : testItem.id, requestOptions : requestOptions); Assert.IsNotNull(itemResponse); Assert.AreEqual(httpStatusCode, itemResponse.StatusCode); Assert.AreEqual(5, testHandlerHitCount, "An operation did not make it to the handler"); using (Stream itemStream = MockCosmosUtil.Serializer.ToStream <dynamic>(testItem)) { using (ResponseMessage streamResponse = await container.CreateItemStreamAsync( partitionKey: partitionKey, streamPayload: itemStream, requestOptions: requestOptions)) { Assert.IsNotNull(streamResponse); Assert.AreEqual(httpStatusCode, streamResponse.StatusCode); } } using (Stream itemStream = MockCosmosUtil.Serializer.ToStream <dynamic>(testItem)) { using (ResponseMessage streamResponse = await container.ReadItemStreamAsync( partitionKey: partitionKey, id: testItem.id, requestOptions: requestOptions)) { Assert.IsNotNull(streamResponse); Assert.AreEqual(httpStatusCode, streamResponse.StatusCode); } } using (Stream itemStream = MockCosmosUtil.Serializer.ToStream <dynamic>(testItem)) { using (ResponseMessage streamResponse = await container.UpsertItemStreamAsync( partitionKey: partitionKey, streamPayload: itemStream, requestOptions: requestOptions)) { Assert.IsNotNull(streamResponse); Assert.AreEqual(httpStatusCode, streamResponse.StatusCode); } } using (Stream itemStream = MockCosmosUtil.Serializer.ToStream <dynamic>(testItem)) { using (ResponseMessage streamResponse = await container.ReplaceItemStreamAsync( partitionKey: partitionKey, id: testItem.id, streamPayload: itemStream, requestOptions: requestOptions)) { Assert.IsNotNull(streamResponse); Assert.AreEqual(httpStatusCode, streamResponse.StatusCode); } } using (Stream itemStream = MockCosmosUtil.Serializer.ToStream <dynamic>(testItem)) { using (ResponseMessage streamResponse = await container.DeleteItemStreamAsync( partitionKey: partitionKey, id: testItem.id, requestOptions: requestOptions)) { Assert.IsNotNull(streamResponse); Assert.AreEqual(httpStatusCode, streamResponse.StatusCode); } } Assert.AreEqual(10, testHandlerHitCount, "A stream operation did not make it to the handler"); }
public async Task DeleteItemsAsync<T>(Container container, string id, string partitionKey, ItemRequestOptions itemRequestOptions = null) { var partitionKeyStruct = new PartitionKey(partitionKey); await container.DeleteItemAsync<T>(id, partitionKeyStruct, itemRequestOptions); }
public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (this._cosmos == null) { throw new ArgumentException("GrainState collection not initialized."); } string id = this.GetKeyString(grainReference); string partitionKey = await this.BuildPartitionKey(grainType, grainReference); if (this._logger.IsEnabled(LogLevel.Trace)) { this._logger.Trace( "Clearing: GrainType={0} Key={1} Grainid={2} ETag={3} DeleteStateOnClear={4} from Collection={4} with PartitionKey {5}", grainType, id, grainReference, grainState.ETag, this._options.DeleteStateOnClear, this._options.Collection, partitionKey); } var pk = new PartitionKey(partitionKey); var requestOptions = new ItemRequestOptions { IfMatchEtag = grainState.ETag }; try { if (this._options.DeleteStateOnClear) { if (string.IsNullOrWhiteSpace(grainState.ETag)) { return; //state not written } await ExecuteWithRetries(() => this._container.DeleteItemAsync <GrainStateEntity>( id, pk, requestOptions)); grainState.ETag = null; } else { var entity = new GrainStateEntity { ETag = grainState.ETag, Id = id, GrainType = grainType, State = null, PartitionKey = partitionKey }; var response = await ExecuteWithRetries(() => string.IsNullOrWhiteSpace(grainState.ETag)? this._container.CreateItemAsync(entity, pk) : this._container.ReplaceItemAsync(entity, entity.Id, pk, requestOptions)) .ConfigureAwait(false); grainState.ETag = response.Resource.ETag; } } catch (Exception exc) { this._logger.LogError(exc, $"Failure clearing state for Grain Type {grainType} with Id {id}."); throw; } }
public Task <ItemResponse <T> > ReadItemAsync <T>(string id, ItemRequestOptions requestOptions = null, CancellationToken cancellationToken = default(CancellationToken)) { return(Container.ReadItemAsync <T>(id, partitionKey, requestOptions, cancellationToken)); }