From 9dc9c7f57a08e7f707758da1e39ad507190d7c2f Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Mon, 5 Feb 2024 20:51:33 -0800 Subject: [PATCH 1/2] 3.38.1: Adds new SDK versions and contract files (#4305) * Code changes to bump up release versions. * Updated changelog. --------- Co-authored-by: REDMOND\adityasa --- Directory.Build.props | 6 +++--- changelog.md | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 8b31c98888..89cc974a3e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,9 +1,9 @@ - 3.38.0 + 3.38.1 3.39.0 - preview.0 - 3.32.0 + preview.1 + 3.32.1 2.0.4 2.1.0 preview4 diff --git a/changelog.md b/changelog.md index 09228b9cfe..d87d89a505 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,21 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.39.0-preview.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.39.0-preview.1) - 2024-02-02 +### [3.38.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.38.1) - 2024-02-02 + +#### Fixed +- [4294](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4294) DisableServerCertificateValidation: Fixes Default HttpClient to honor DisableServerCertificateValidation (#4294) + +#### Added +- [4299](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4299) Query: Adds environment variable for overriding EnableOptimisticDirectExecution default (#4299) + > Note: This change provides another way to manage the upgrade to `3.38`. It provides an option to avoid potential disruption due to the breaking change (see the note below) if only config deployment is preferred, instead of any explicit code modification. + > With this change, users can set the environment variable AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED to false in their production environments while upgrading from previous minor version (`3.37` or below) to `3.38.1` (or above). + > This will signal the SDK to disable Optimistic Direct Execution by default. + > Once the environment is fully upgraded to the target version, the environment variable can be removed (or set to true) to enable ODE. + > It is recommended that the environment variable is used only to manage the upgrade and removed once the deployment is complete. + > Please note that environment variable acts as the override only for choosing the default value. If the code explicitly modifies the setting, that value will be honored during actual operations. + ### [3.39.0-preview.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.39.0-preview.0) - 2024-01-31 #### Added From 04e1d08e917c91a11e238f035284ae5c7679397a Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 1 Feb 2024 18:34:35 -0800 Subject: [PATCH 2/2] [Internal] Query: Adds environment variable for overriding EnableOptimisticDirectExecution default (#4299) * Configured default value for EnableOptimisticDirectExecution setting to honor environment variable. * Updated tests to include case insensitive checks no environment variable name. * Addressed comments. * Removed unused using. --- .../src/RequestOptions/QueryRequestOptions.cs | 2 +- .../src/Util/ConfigurationManager.cs | 17 +++ .../OptimisticDirectExecutionQueryTests.cs | 144 +++++++++++++++++- 3 files changed, 157 insertions(+), 6 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 7d4da6f535..1035fac1c9 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -50,7 +50,7 @@ public class QueryRequestOptions : RequestOptions /// /// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query. /// - public bool EnableOptimisticDirectExecution { get; set; } = true; + public bool EnableOptimisticDirectExecution { get; set; } = ConfigurationManager.IsOptimisticDirectExecutionEnabled(defaultValue: true); /// /// Gets or sets the maximum number of items that can be buffered client side during diff --git a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs index 3c48b1f5ab..1be83b2430 100644 --- a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs +++ b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs @@ -22,6 +22,11 @@ internal static class ConfigurationManager /// internal static readonly string PartitionLevelFailoverEnabled = "AZURE_COSMOS_PARTITION_LEVEL_FAILOVER_ENABLED"; + /// + /// Environment variable name for overriding optimistic direct execution of queries. + /// + internal static readonly string OptimisticDirectExecutionEnabled = "AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED"; + public static T GetEnvironmentVariable(string variable, T defaultValue) { string value = Environment.GetEnvironmentVariable(variable); @@ -72,5 +77,17 @@ public static bool IsPartitionLevelFailoverEnabled( variable: ConfigurationManager.PartitionLevelFailoverEnabled, defaultValue: defaultValue); } + + /// + /// Gets the boolean value indicating whether optimistic direct execution is enabled based on the environment variable override. + /// + public static bool IsOptimisticDirectExecutionEnabled( + bool defaultValue) + { + return ConfigurationManager + .GetEnvironmentVariable( + variable: OptimisticDirectExecutionEnabled, + defaultValue: defaultValue); + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index cb70aacb41..dbcfafa5ad 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -524,6 +524,136 @@ public async Task TestClientDisableOdeDefaultValue() bool success = bool.TryParse(properties.QueryEngineConfiguration[ClientDisableOptimisticDirectExecution].ToString(), out bool clientDisablOde); Assert.IsTrue(success, $"Parsing must succeed. Value supplied '{ClientDisableOptimisticDirectExecution}'"); Assert.IsFalse(clientDisablOde); + } + + [TestMethod] + public async Task TestOdeEnvironmentVariable() + { + QueryRequestOptions options = new QueryRequestOptions(); + Assert.IsTrue(options.EnableOptimisticDirectExecution); + + foreach ((string name, string value, bool expectedValue) in new[] + { + // Environment variables are case insensitive in windows + ("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", "true", true), + ("AZURE_COSMOS_optimistic_direct_execution_enabled", "True", true), + ("azure_cosmos_optimistic_direct_execution_enabled", "TRUE", true), + ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", "truE", true), + ("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", "false", false), + ("AZURE_COSMOS_optimistic_direct_execution_enabled", "False", false), + ("azure_cosmos_optimistic_direct_execution_enabled", "FALSE", false), + ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", "false", false), + ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", string.Empty, true), + (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), "false", true), + (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), null, true), + ("enableode", "false", true) + }) + { + try + { + // Test new value + Environment.SetEnvironmentVariable(name, value); + QueryRequestOptions options2 = new QueryRequestOptions(); + bool areEqual = expectedValue == options2.EnableOptimisticDirectExecution; + Assert.IsTrue(areEqual, $"EnvironmentVariable:'{name}', value:'{value}', expected:'{expectedValue}', actual:'{options2.EnableOptimisticDirectExecution}'"); + } + finally + { + // Remove side effects. + Environment.SetEnvironmentVariable(name, null); + } + } + + foreach (string value in new[] + { + "'", + "-", + "asdf", + "'true'", + "'false'" + }) + { + bool receivedException = false; + try + { + // Test new value + Environment.SetEnvironmentVariable("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", value); + QueryRequestOptions options2 = new QueryRequestOptions(); + } + catch(FormatException fe) + { + Assert.IsTrue(fe.ToString().Contains($@"String '{value}' was not recognized as a valid Boolean.")); + receivedException = true; + } + finally + { + // Remove side effects. + Environment.SetEnvironmentVariable("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", null); + } + + Assert.IsTrue(receivedException, $"Expected exception was not received for value '{value}'"); + } + + await this.TestQueryExecutionUsingODEEnvironmentVariable( + environmentVariableValue: "false", + expectODEPipeline: false); + + await this.TestQueryExecutionUsingODEEnvironmentVariable( + environmentVariableValue: "true", + expectODEPipeline: true); + } + + private async Task TestQueryExecutionUsingODEEnvironmentVariable(string environmentVariableValue, bool expectODEPipeline) + { + IReadOnlyList empty = new List(0); + IReadOnlyList first5Integers = Enumerable.Range(0, 5).ToList(); + IReadOnlyList first7Integers = Enumerable.Range(0, NumberOfDocuments).ToList(); + IReadOnlyList first7IntegersReversed = Enumerable.Range(0, NumberOfDocuments).Reverse().ToList(); + + try + { + // Test query execution using environment variable + Environment.SetEnvironmentVariable("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", environmentVariableValue); + PartitionKey partitionKeyValue = new PartitionKey("/value"); + List singlePartitionContainerTestCases = new List() + { + CreateInput( + query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{PartitionKeyField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: null, // Uses environment variable + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: expectODEPipeline ? TestInjections.PipelineType.OptimisticDirectExecution : TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{PartitionKeyField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: false, // Overrides environment variable + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{PartitionKeyField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, // Overrides environment variable + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + }; + + IReadOnlyList documents = CreateDocuments(NumberOfDocuments, PartitionKeyField, NumberField, NullField); + + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct | ConnectionModes.Gateway, + CollectionTypes.SinglePartition, + documents, + (container, documents) => RunTests(singlePartitionContainerTestCases, container), + "/" + PartitionKeyField); + } + finally + { + // Attempt to protect other ODE tests from side-effects in case of test failure. + Environment.SetEnvironmentVariable("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", null); + } } private static async Task RunTests(IEnumerable testCases, Container container) @@ -536,9 +666,13 @@ private static async Task RunTests(IEnumerable testCase { MaxItemCount = pageSize, PartitionKey = testCase.PartitionKey, - EnableOptimisticDirectExecution = testCase.EnableOptimisticDirectExecution, TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, new TestInjections.ResponseStats()) - }; + }; + + if(testCase.EnableOptimisticDirectExecution.HasValue) + { + feedOptions.EnableOptimisticDirectExecution = testCase.EnableOptimisticDirectExecution.Value; + } List items = await RunQueryAsync( container, @@ -600,7 +734,7 @@ private static DirectExecutionTestCase CreateInput( string query, IReadOnlyList expectedResult, PartitionKey? partitionKey, - bool enableOptimisticDirectExecution, + bool? enableOptimisticDirectExecution, int[] pageSizeOptions, TestInjections.PipelineType expectedPipelineType) { @@ -612,7 +746,7 @@ private readonly struct DirectExecutionTestCase public string Query { get; } public IReadOnlyList ExpectedResult { get; } public PartitionKey? PartitionKey { get; } - public bool EnableOptimisticDirectExecution { get; } + public bool? EnableOptimisticDirectExecution { get; } public int[] PageSizeOptions { get; } public TestInjections.PipelineType ExpectedPipelineType { get; } @@ -620,7 +754,7 @@ public DirectExecutionTestCase( string query, IReadOnlyList expectedResult, PartitionKey? partitionKey, - bool enableOptimisticDirectExecution, + bool? enableOptimisticDirectExecution, int[] pageSizeOptions, TestInjections.PipelineType expectedPipelineType) {