Skip to content

Commit fa6097d

Browse files
[Internal] Binary Encoding: Adds Client Option to Enable/Disable Request and Response Stream Conversation (#5123)
# Pull Request Template ## Description Create a new internal cosmos client options: `EnableStreamPassThrough` to enable or disable the request/ response stream conversation. When enabled, the request and/or response stream would not be converted to the desired target serialization type and would act just like a pass-through. The default value for this parameter is `False`. **Usage:** ``` CosmosClientOptions clientOptions = new CosmosClientOptions() { EnableStreamPassThrough = true, }; CosmosClient cosmosClient = new ( endpoint, authKey, clientOptions); ``` ## Type of change Please delete options that are not relevant. - [x] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) ## Closing issues To automatically close an issue: closes #5122
1 parent 171259c commit fa6097d

3 files changed

Lines changed: 144 additions & 2 deletions

File tree

Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,14 @@ public System.Text.Json.JsonSerializerOptions UseSystemTextJsonSerializerWithOpt
452452
/// The default value is 'true'.
453453
/// </summary>
454454
internal bool EnableAsyncCacheExceptionNoSharing { get; set; } = true;
455+
456+
/// <summary>
457+
/// Gets or sets the boolean flag to skip converting a text stream to binary and vice versa. When enabled, the request and response stream
458+
/// would not be converted to the desired target serialization type and will act just like a pass through. This client option will
459+
/// remain internal only since the consumer of this flag will be the internal components of the cosmos db ecosystem.
460+
/// The default value for this parameter is 'false'.
461+
/// </summary>
462+
internal bool EnableStreamPassThrough { get; set; } = false;
455463

456464
/// <summary>
457465
/// (Direct/TCP) Controls the amount of idle time after which unused connections are closed.

Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,8 @@ private async Task<ResponseMessage> ProcessItemStreamAsync(
934934
// engine, which does not support binary encoded content at the moment. For long term, since trigger operations won't
935935
// be supported in the backend, avoiding the binary encoding in such cases, will be the ideal approach.
936936
if (ConfigurationManager.IsBinaryEncodingEnabled()
937-
&& !ContainerCore.IsTriggerPresentInRequestOptions(requestOptions))
937+
&& !ContainerCore.IsTriggerPresentInRequestOptions(requestOptions)
938+
&& !this.ClientContext.ClientOptions.EnableStreamPassThrough)
938939
{
939940
streamPayload = CosmosSerializationUtil.TrySerializeStreamToTargetFormat(
940941
targetSerializationFormat: ContainerCore.GetTargetRequestSerializationFormat(),
@@ -957,7 +958,8 @@ private async Task<ResponseMessage> ProcessItemStreamAsync(
957958
cancellationToken: cancellationToken);
958959

959960
// Convert Binary Stream to Text.
960-
if (targetResponseSerializationFormat.HasValue
961+
if (!this.ClientContext.ClientOptions.EnableStreamPassThrough
962+
&& targetResponseSerializationFormat.HasValue
961963
&& (requestOptions == null || !requestOptions.EnableBinaryResponseOnPointOperations)
962964
&& responseMessage?.Content is CloneableStream outputCloneableStream)
963965
{

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,138 @@ public async Task CreateDropItemStreamTest(bool binaryEncodingEnabledInClient, b
768768
{
769769
Environment.SetEnvironmentVariable(ConfigurationManager.BinaryEncodingEnabled, null);
770770
}
771+
}
772+
773+
[TestMethod]
774+
[Owner("dkunda")]
775+
[DataRow(true, true, DisplayName = "Test scenario when binary encoding is enabled at client level and stream conversation for binary encoding is skipped.")]
776+
[DataRow(true, false, DisplayName = "Test scenario when binary encoding is enabled at client level and stream conversation for binary encoding is enabled.")]
777+
[DataRow(false, true, DisplayName = "Test scenario when binary encoding is disabled at client level and stream conversation for binary encoding is skipped.")]
778+
[DataRow(false, false, DisplayName = "Test scenario when binary encoding is disabled at client level and stream conversation for binary encoding is enabled.")]
779+
public async Task CreateItemStream_WithEnableBinaryResponseOptions_ShouldSkipStreamConversation(
780+
bool binaryEncodingEnabledInClient,
781+
bool enableStreamPassThrough)
782+
{
783+
Cosmos.Database database = null;
784+
Container container = null;
785+
try
786+
{
787+
string databaseName = "binary-encoding-db";
788+
string containerName = "binary-encoding-container";
789+
if (binaryEncodingEnabledInClient)
790+
{
791+
Environment.SetEnvironmentVariable(ConfigurationManager.BinaryEncodingEnabled, "True");
792+
}
793+
794+
(string endpoint, string authKey) = TestCommon.GetAccountInfo();
795+
CosmosClientOptions clientOptions = new CosmosClientOptions()
796+
{
797+
EnableStreamPassThrough = enableStreamPassThrough,
798+
};
799+
800+
CosmosClient cosmosClient = new (
801+
endpoint,
802+
authKey,
803+
clientOptions);
804+
805+
DatabaseResponse dbResponse = await cosmosClient.CreateDatabaseIfNotExistsAsync(databaseName);
806+
database = dbResponse.Database;
807+
808+
ContainerProperties properties = new (id: containerName, partitionKeyPath: "/pk");
809+
container = await database.CreateContainerIfNotExistsAsync(properties);
810+
811+
ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity();
812+
CosmosSerializerCore cosmosSerializer = new CosmosSerializerCore();
813+
using (Stream stream = cosmosSerializer.ToStream<ToDoActivity>(
814+
testItem,
815+
canUseBinaryEncodingForPointOperations: binaryEncodingEnabledInClient))
816+
{
817+
if (binaryEncodingEnabledInClient)
818+
{
819+
// Asserting the input stream is in binary format.
820+
AssertOnResponseSerializationBinaryType(stream);
821+
}
822+
else
823+
{
824+
// Asserting the input stream is in text format.
825+
AssertOnResponseSerializationTextType(stream);
826+
}
827+
828+
using (ResponseMessage response = await container.CreateItemStreamAsync(
829+
streamPayload: stream,
830+
partitionKey: new Cosmos.PartitionKey(testItem.pk)))
831+
{
832+
Assert.IsNotNull(response);
833+
Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);
834+
Assert.IsTrue(response.Headers.RequestCharge > 0);
835+
Assert.IsNotNull(response.Headers.ActivityId);
836+
Assert.IsNotNull(response.Headers.ETag);
837+
Assert.IsNotNull(response.Diagnostics);
838+
Assert.IsTrue(!string.IsNullOrEmpty(response.Diagnostics.ToString()));
839+
Assert.IsTrue(response.Diagnostics.GetClientElapsedTime() > TimeSpan.Zero);
840+
841+
if (!enableStreamPassThrough)
842+
{
843+
AssertOnResponseSerializationTextType(response.Content);
844+
}
845+
else
846+
{
847+
if (binaryEncodingEnabledInClient)
848+
{
849+
AssertOnResponseSerializationBinaryType(response.Content);
850+
}
851+
else
852+
{
853+
AssertOnResponseSerializationTextType(response.Content);
854+
}
855+
}
856+
}
857+
}
858+
859+
using (ResponseMessage response = await container.ReadItemStreamAsync(
860+
id: testItem.id,
861+
partitionKey: new Cosmos.PartitionKey(testItem.pk)))
862+
{
863+
Assert.IsNotNull(response);
864+
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
865+
Assert.IsTrue(response.Headers.RequestCharge > 0);
866+
Assert.IsNotNull(response.Headers.ActivityId);
867+
Assert.IsNotNull(response.Headers.ETag);
868+
Assert.IsNotNull(response.Diagnostics);
869+
Assert.IsTrue(!string.IsNullOrEmpty(response.Diagnostics.ToString()));
870+
Assert.IsTrue(response.Diagnostics.GetClientElapsedTime() > TimeSpan.Zero);
871+
872+
if (!enableStreamPassThrough)
873+
{
874+
AssertOnResponseSerializationTextType(response.Content);
875+
}
876+
else
877+
{
878+
if (binaryEncodingEnabledInClient)
879+
{
880+
AssertOnResponseSerializationBinaryType(response.Content);
881+
}
882+
else
883+
{
884+
AssertOnResponseSerializationTextType(response.Content);
885+
}
886+
}
887+
}
888+
}
889+
finally
890+
{
891+
Environment.SetEnvironmentVariable(ConfigurationManager.BinaryEncodingEnabled, null);
892+
893+
if (container != null)
894+
{
895+
await container.DeleteContainerStreamAsync();
896+
}
897+
898+
if (database != null)
899+
{
900+
await database.DeleteAsync();
901+
}
902+
}
771903
}
772904

773905
[TestMethod]

0 commit comments

Comments
 (0)