Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bulk: Adds validation for ItemRequestOptions.Properties #2746

Merged
merged 7 commits into from
Sep 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ internal virtual async Task ValidateOperationAsync(
|| itemRequestOptions.PreTriggers != null
|| itemRequestOptions.PostTriggers != null
|| itemRequestOptions.SessionToken != null
|| itemRequestOptions.Properties != null
|| itemRequestOptions.DedicatedGatewayRequestOptions?.MaxIntegratedCacheStaleness != null)
{
throw new InvalidOperationException(ClientResources.UnsupportedBulkRequestOptions);
Expand Down
8 changes: 3 additions & 5 deletions Microsoft.Azure.Cosmos/src/ClientResources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Microsoft.Azure.Cosmos/src/ClientResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@
<value>Instantiation of only value types, anonymous types and spatial types are supported.</value>
</data>
<data name="UnsupportedBulkRequestOptions" xml:space="preserve">
<value>Consistency, Session, and Triggers are not allowed when AllowBulkExecution is set to true.</value>
<value>Consistency, Session, Properties, and Triggers are not allowed when AllowBulkExecution is set to true.</value>
</data>
<data name="EncryptorNotConfigured" xml:space="preserve">
<value>The client was not configured to allow for encryption. Create the client by using cosmosClientBuilder.WithEncryptor.</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Tracing;
using Microsoft.Azure.Documents;
Expand All @@ -16,7 +15,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests
[TestClass]
public class BatchAsyncContainerExecutorTests
{
private static CosmosSerializer cosmosDefaultJsonSerializer = new CosmosJsonDotNetSerializer();
private readonly static CosmosSerializer cosmosDefaultJsonSerializer = new CosmosJsonDotNetSerializer();
private CosmosClient cosmosClient;
private ContainerInternal cosmosContainer;

Expand Down Expand Up @@ -79,6 +78,9 @@ public async Task ValidateInvalidRequestOptionsAsync()
MyDocument myDocument = new MyDocument() { id = id, Status = id };

await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => executor.ValidateOperationAsync(new ItemBatchOperation(OperationType.Replace, 0, new Cosmos.PartitionKey(id), id, cosmosDefaultJsonSerializer.ToStream(myDocument)), new ItemRequestOptions() { SessionToken = "something" }));
await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => executor.ValidateOperationAsync(
new ItemBatchOperation(OperationType.Replace, 0, new Cosmos.PartitionKey(id), id, cosmosDefaultJsonSerializer.ToStream(myDocument)),
new ItemRequestOptions() { Properties = new Dictionary<string, object>() { { "test", "test" } } }));
await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => executor.ValidateOperationAsync(
new ItemBatchOperation(OperationType.Replace, 0, new Cosmos.PartitionKey(id), id, cosmosDefaultJsonSerializer.ToStream(myDocument)),
new ItemRequestOptions() { DedicatedGatewayRequestOptions = new DedicatedGatewayRequestOptions { MaxIntegratedCacheStaleness = TimeSpan.FromMinutes(3) } }));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests
public class CosmosItemBulkTests
{
private Container container;
private Container nonBulkContainer;
private Database database;

[TestInitialize]
Expand All @@ -26,14 +25,12 @@ public async Task TestInitialize()
AllowBulkExecution = true
};
CosmosClient client = TestCommon.CreateCosmosClient(clientOptions);
CosmosClient nonBulkClient = TestCommon.CreateCosmosClient();

DatabaseResponse response = await client.CreateDatabaseIfNotExistsAsync(Guid.NewGuid().ToString());
this.database = response.Database;

ContainerResponse containerResponse = await this.database.CreateContainerAsync(Guid.NewGuid().ToString(), "/pk", 10000);
this.container = containerResponse;
this.nonBulkContainer = nonBulkClient.GetContainer(this.database.Id, this.container.Id);
}

[TestCleanup]
Expand All @@ -42,13 +39,47 @@ public async Task Cleanup()
await this.database.DeleteAsync();
}

[TestMethod]
public async Task ValidateRequestOptions()
{
async Task ExecuteAndValidateCreateItemAsync(int i)
{
try
{
await CosmosItemBulkTests.ExecuteCreateStreamAsync(
this.container,
CosmosItemBulkTests.CreateItem(i.ToString()),
new ItemRequestOptions()
{
Properties = new Dictionary<string, object>() { { "test", "test" } },
DedicatedGatewayRequestOptions = new DedicatedGatewayRequestOptions { MaxIntegratedCacheStaleness = TimeSpan.FromMinutes(3) },
SessionToken = Guid.NewGuid().ToString(),
PreTriggers = new List<string>() { "preTrigger" },
PostTriggers = new List<string>() { "postTrigger" }
});
Assert.Fail("Request should have failed");
}
catch (InvalidOperationException)
{
}
}

List<Task> tasks = new List<Task>();
for (int i = 0; i < 100; i++)
{
tasks.Add(ExecuteAndValidateCreateItemAsync(i));
}

await Task.WhenAll(tasks);
}

[TestMethod]
public async Task CreateItemStream_WithBulk()
{
List<Task<ResponseMessage>> tasks = new List<Task<ResponseMessage>>();
for (int i = 0; i < 100; i++)
{
tasks.Add(ExecuteCreateStreamAsync(this.container, CreateItem(i.ToString())));
tasks.Add(CosmosItemBulkTests.ExecuteCreateStreamAsync(this.container, CosmosItemBulkTests.CreateItem(i.ToString())));
}

await Task.WhenAll(tasks);
Expand All @@ -73,7 +104,7 @@ public async Task CreateItemAsync_WithBulk()
List<Task<ItemResponse<ToDoActivity>>> tasks = new List<Task<ItemResponse<ToDoActivity>>>();
for (int i = 0; i < 100; i++)
{
tasks.Add(ExecuteCreateAsync(this.container, CreateItem(i.ToString())));
tasks.Add(CosmosItemBulkTests.ExecuteCreateAsync(this.container, CosmosItemBulkTests.CreateItem(i.ToString())));
}

await Task.WhenAll(tasks);
Expand All @@ -96,7 +127,7 @@ public async Task CreateItemJObjectWithoutPK_WithBulk()
List<Task<ItemResponse<JObject>>> tasks = new List<Task<ItemResponse<JObject>>>();
for (int i = 0; i < 100; i++)
{
tasks.Add(this.container.CreateItemAsync(CreateJObjectWithoutPK(i.ToString())));
tasks.Add(this.container.CreateItemAsync(CosmosItemBulkTests.CreateJObjectWithoutPK(i.ToString())));
}

await Task.WhenAll(tasks);
Expand All @@ -119,7 +150,7 @@ public async Task UpsertItemStream_WithBulk()
List<Task<ResponseMessage>> tasks = new List<Task<ResponseMessage>>();
for (int i = 0; i < 100; i++)
{
tasks.Add(ExecuteUpsertStreamAsync(this.container, CreateItem(i.ToString())));
tasks.Add(CosmosItemBulkTests.ExecuteUpsertStreamAsync(this.container, CosmosItemBulkTests.CreateItem(i.ToString())));
}

await Task.WhenAll(tasks);
Expand All @@ -144,7 +175,7 @@ public async Task UpsertItem_WithBulk()
List<Task<ItemResponse<ToDoActivity>>> tasks = new List<Task<ItemResponse<ToDoActivity>>>();
for (int i = 0; i < 100; i++)
{
tasks.Add(ExecuteUpsertAsync(this.container, CreateItem(i.ToString())));
tasks.Add(CosmosItemBulkTests.ExecuteUpsertAsync(this.container, CosmosItemBulkTests.CreateItem(i.ToString())));
}

await Task.WhenAll(tasks);
Expand All @@ -169,9 +200,9 @@ public async Task DeleteItemStream_WithBulk()
List<Task<ResponseMessage>> tasks = new List<Task<ResponseMessage>>();
for (int i = 0; i < 100; i++)
{
ToDoActivity createdDocument = CreateItem(i.ToString());
ToDoActivity createdDocument = CosmosItemBulkTests.CreateItem(i.ToString());
createdDocuments.Add(createdDocument);
tasks.Add(ExecuteCreateStreamAsync(this.container, createdDocument));
tasks.Add(CosmosItemBulkTests.ExecuteCreateStreamAsync(this.container, createdDocument));
}

await Task.WhenAll(tasks);
Expand All @@ -180,7 +211,7 @@ public async Task DeleteItemStream_WithBulk()
// Delete the items
foreach (ToDoActivity createdDocument in createdDocuments)
{
deleteTasks.Add(ExecuteDeleteStreamAsync(this.container, createdDocument));
deleteTasks.Add(CosmosItemBulkTests.ExecuteDeleteStreamAsync(this.container, createdDocument));
}

await Task.WhenAll(deleteTasks);
Expand All @@ -204,9 +235,9 @@ public async Task DeleteItem_WithBulk()
List<Task<ItemResponse<ToDoActivity>>> tasks = new List<Task<ItemResponse<ToDoActivity>>>();
for (int i = 0; i < 100; i++)
{
ToDoActivity createdDocument = CreateItem(i.ToString());
ToDoActivity createdDocument = CosmosItemBulkTests.CreateItem(i.ToString());
createdDocuments.Add(createdDocument);
tasks.Add(ExecuteCreateAsync(this.container, createdDocument));
tasks.Add(CosmosItemBulkTests.ExecuteCreateAsync(this.container, createdDocument));
}

await Task.WhenAll(tasks);
Expand All @@ -215,7 +246,7 @@ public async Task DeleteItem_WithBulk()
// Delete the items
foreach (ToDoActivity createdDocument in createdDocuments)
{
deleteTasks.Add(ExecuteDeleteAsync(this.container, createdDocument));
deleteTasks.Add(CosmosItemBulkTests.ExecuteDeleteAsync(this.container, createdDocument));
}

await Task.WhenAll(deleteTasks);
Expand All @@ -239,9 +270,9 @@ public async Task ReadItemStream_WithBulk()
List<Task<ResponseMessage>> tasks = new List<Task<ResponseMessage>>();
for (int i = 0; i < 100; i++)
{
ToDoActivity createdDocument = CreateItem(i.ToString());
ToDoActivity createdDocument = CosmosItemBulkTests.CreateItem(i.ToString());
createdDocuments.Add(createdDocument);
tasks.Add(ExecuteCreateStreamAsync(this.container, createdDocument));
tasks.Add(CosmosItemBulkTests.ExecuteCreateStreamAsync(this.container, createdDocument));
}

await Task.WhenAll(tasks);
Expand All @@ -250,7 +281,7 @@ public async Task ReadItemStream_WithBulk()
// Read the items
foreach (ToDoActivity createdDocument in createdDocuments)
{
readTasks.Add(ExecuteReadStreamAsync(this.container, createdDocument));
readTasks.Add(CosmosItemBulkTests.ExecuteReadStreamAsync(this.container, createdDocument));
}

await Task.WhenAll(readTasks);
Expand All @@ -274,9 +305,9 @@ public async Task ReadItem_WithBulk()
List<Task<ItemResponse<ToDoActivity>>> tasks = new List<Task<ItemResponse<ToDoActivity>>>();
for (int i = 0; i < 100; i++)
{
ToDoActivity createdDocument = CreateItem(i.ToString());
ToDoActivity createdDocument = CosmosItemBulkTests.CreateItem(i.ToString());
createdDocuments.Add(createdDocument);
tasks.Add(ExecuteCreateAsync(this.container, createdDocument));
tasks.Add(CosmosItemBulkTests.ExecuteCreateAsync(this.container, createdDocument));
}

await Task.WhenAll(tasks);
Expand All @@ -285,7 +316,7 @@ public async Task ReadItem_WithBulk()
// Read the items
foreach (ToDoActivity createdDocument in createdDocuments)
{
readTasks.Add(ExecuteReadAsync(this.container, createdDocument));
readTasks.Add(CosmosItemBulkTests.ExecuteReadAsync(this.container, createdDocument));
}

await Task.WhenAll(readTasks);
Expand All @@ -309,9 +340,9 @@ public async Task ReplaceItemStream_WithBulk()
List<Task<ResponseMessage>> tasks = new List<Task<ResponseMessage>>();
for (int i = 0; i < 100; i++)
{
ToDoActivity createdDocument = CreateItem(i.ToString());
ToDoActivity createdDocument = CosmosItemBulkTests.CreateItem(i.ToString());
createdDocuments.Add(createdDocument);
tasks.Add(ExecuteCreateStreamAsync(this.container, createdDocument));
tasks.Add(CosmosItemBulkTests.ExecuteCreateStreamAsync(this.container, createdDocument));
}

await Task.WhenAll(tasks);
Expand All @@ -320,7 +351,7 @@ public async Task ReplaceItemStream_WithBulk()
// Replace the items
foreach (ToDoActivity createdDocument in createdDocuments)
{
replaceTasks.Add(ExecuteReplaceStreamAsync(this.container, createdDocument));
replaceTasks.Add(CosmosItemBulkTests.ExecuteReplaceStreamAsync(this.container, createdDocument));
}

await Task.WhenAll(replaceTasks);
Expand All @@ -344,9 +375,9 @@ public async Task ReplaceItem_WithBulk()
List<Task<ItemResponse<ToDoActivity>>> tasks = new List<Task<ItemResponse<ToDoActivity>>>();
for (int i = 0; i < 100; i++)
{
ToDoActivity createdDocument = CreateItem(i.ToString());
ToDoActivity createdDocument = CosmosItemBulkTests.CreateItem(i.ToString());
createdDocuments.Add(createdDocument);
tasks.Add(ExecuteCreateAsync(this.container, createdDocument));
tasks.Add(CosmosItemBulkTests.ExecuteCreateAsync(this.container, createdDocument));
}

await Task.WhenAll(tasks);
Expand All @@ -355,7 +386,7 @@ public async Task ReplaceItem_WithBulk()
// Replace the items
foreach (ToDoActivity createdDocument in createdDocuments)
{
replaceTasks.Add(ExecuteReplaceAsync(this.container, createdDocument));
replaceTasks.Add(CosmosItemBulkTests.ExecuteReplaceAsync(this.container, createdDocument));
}

await Task.WhenAll(replaceTasks);
Expand All @@ -379,9 +410,9 @@ public async Task PatchItemStream_WithBulk()
List<Task<ResponseMessage>> tasks = new List<Task<ResponseMessage>>();
for (int i = 0; i < 100; i++)
{
ToDoActivity createdDocument = CreateItem(i.ToString());
ToDoActivity createdDocument = CosmosItemBulkTests.CreateItem(i.ToString());
createdDocuments.Add(createdDocument);
tasks.Add(ExecuteCreateStreamAsync(this.container, createdDocument));
tasks.Add(CosmosItemBulkTests.ExecuteCreateStreamAsync(this.container, createdDocument));
}

await Task.WhenAll(tasks);
Expand All @@ -394,7 +425,7 @@ public async Task PatchItemStream_WithBulk()
// Patch the items
foreach (ToDoActivity createdDocument in createdDocuments)
{
PatchTasks.Add(ExecutePatchStreamAsync((ContainerInternal)this.container, createdDocument, patch));
PatchTasks.Add(CosmosItemBulkTests.ExecutePatchStreamAsync((ContainerInternal)this.container, createdDocument, patch));
}

await Task.WhenAll(PatchTasks);
Expand All @@ -418,9 +449,9 @@ public async Task PatchItem_WithBulk()
List<Task<ItemResponse<ToDoActivity>>> tasks = new List<Task<ItemResponse<ToDoActivity>>>();
for (int i = 0; i < 100; i++)
{
ToDoActivity createdDocument = CreateItem(i.ToString());
ToDoActivity createdDocument = CosmosItemBulkTests.CreateItem(i.ToString());
createdDocuments.Add(createdDocument);
tasks.Add(ExecuteCreateAsync(this.container, createdDocument));
tasks.Add(CosmosItemBulkTests.ExecuteCreateAsync(this.container, createdDocument));
}

await Task.WhenAll(tasks);
Expand All @@ -433,7 +464,7 @@ public async Task PatchItem_WithBulk()
// Patch the items
foreach (ToDoActivity createdDocument in createdDocuments)
{
patchTasks.Add(ExecutePatchAsync((ContainerInternal)this.container, createdDocument, patch));
patchTasks.Add(CosmosItemBulkTests.ExecutePatchAsync((ContainerInternal)this.container, createdDocument, patch));
}

await Task.WhenAll(patchTasks);
Expand Down Expand Up @@ -470,10 +501,10 @@ private async Task CreateLargeItemStreamWithBulk(int appxItemSize)
List<Task<ResponseMessage>> tasks = new List<Task<ResponseMessage>>();
for (int i = 0; i < 3; i++)
{
ToDoActivity item = CreateItem(i.ToString());
ToDoActivity item = CosmosItemBulkTests.CreateItem(i.ToString());

if (i == 1) { item.description = new string('x', appxItemSize); }
tasks.Add(ExecuteCreateStreamAsync(this.container, item));
tasks.Add(CosmosItemBulkTests.ExecuteCreateStreamAsync(this.container, item));
}

await Task.WhenAll(tasks);
Expand Down Expand Up @@ -532,9 +563,9 @@ private static Task<ItemResponse<ToDoActivity>> ExecuteReadAsync(Container conta
return container.ReadItemAsync<ToDoActivity>(item.id, new PartitionKey(item.pk));
}

private static Task<ResponseMessage> ExecuteCreateStreamAsync(Container container, ToDoActivity item)
private static Task<ResponseMessage> ExecuteCreateStreamAsync(Container container, ToDoActivity item, ItemRequestOptions itemRequestOptions = null)
{
return container.CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(item), new PartitionKey(item.pk));
return container.CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(item), new PartitionKey(item.pk), itemRequestOptions);
}

private static Task<ResponseMessage> ExecuteUpsertStreamAsync(Container container, ToDoActivity item)
Expand Down