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

[Internal] Query: Adds environment variable for overriding EnableOptimisticDirectExecution default #4304

Closed
wants to merge 1 commit into from
Closed
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 @@ -50,7 +50,7 @@ public class QueryRequestOptions : RequestOptions
/// <value>
/// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query.
/// </value>
public bool EnableOptimisticDirectExecution { get; set; } = true;
public bool EnableOptimisticDirectExecution { get; set; } = ConfigurationManager.IsOptimisticDirectExecutionEnabled(defaultValue: true);

/// <summary>
/// Gets or sets the maximum number of items that can be buffered client side during
Expand Down
17 changes: 17 additions & 0 deletions Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ internal static class ConfigurationManager
/// </summary>
internal static readonly string PartitionLevelFailoverEnabled = "AZURE_COSMOS_PARTITION_LEVEL_FAILOVER_ENABLED";

/// <summary>
/// Environment variable name for overriding optimistic direct execution of queries.
/// </summary>
internal static readonly string OptimisticDirectExecutionEnabled = "AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED";

public static T GetEnvironmentVariable<T>(string variable, T defaultValue)
{
string value = Environment.GetEnvironmentVariable(variable);
Expand Down Expand Up @@ -72,5 +77,17 @@ public static bool IsPartitionLevelFailoverEnabled(
variable: ConfigurationManager.PartitionLevelFailoverEnabled,
defaultValue: defaultValue);
}

/// <summary>
/// Gets the boolean value indicating whether optimistic direct execution is enabled based on the environment variable override.
/// </summary>
public static bool IsOptimisticDirectExecutionEnabled(
bool defaultValue)
{
return ConfigurationManager
.GetEnvironmentVariable(
variable: OptimisticDirectExecutionEnabled,
defaultValue: defaultValue);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<int> empty = new List<int>(0);
IReadOnlyList<int> first5Integers = Enumerable.Range(0, 5).ToList();
IReadOnlyList<int> first7Integers = Enumerable.Range(0, NumberOfDocuments).ToList();
IReadOnlyList<int> 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<DirectExecutionTestCase> singlePartitionContainerTestCases = new List<DirectExecutionTestCase>()
{
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<string> 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<DirectExecutionTestCase> testCases, Container container)
Expand All @@ -536,9 +666,13 @@ private static async Task RunTests(IEnumerable<DirectExecutionTestCase> 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<CosmosElement> items = await RunQueryAsync(
container,
Expand Down Expand Up @@ -600,7 +734,7 @@ private static DirectExecutionTestCase CreateInput(
string query,
IReadOnlyList<int> expectedResult,
PartitionKey? partitionKey,
bool enableOptimisticDirectExecution,
bool? enableOptimisticDirectExecution,
int[] pageSizeOptions,
TestInjections.PipelineType expectedPipelineType)
{
Expand All @@ -612,15 +746,15 @@ private readonly struct DirectExecutionTestCase
public string Query { get; }
public IReadOnlyList<int> ExpectedResult { get; }
public PartitionKey? PartitionKey { get; }
public bool EnableOptimisticDirectExecution { get; }
public bool? EnableOptimisticDirectExecution { get; }
public int[] PageSizeOptions { get; }
public TestInjections.PipelineType ExpectedPipelineType { get; }

public DirectExecutionTestCase(
string query,
IReadOnlyList<int> expectedResult,
PartitionKey? partitionKey,
bool enableOptimisticDirectExecution,
bool? enableOptimisticDirectExecution,
int[] pageSizeOptions,
TestInjections.PipelineType expectedPipelineType)
{
Expand Down
Loading