Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Configured default value for EnableOptimisticDirectExecution setting …
…to honor environment variable.
  • Loading branch information
adityasa committed Feb 1, 2024
commit d6a94f155f84913916ee9d8074489c760b03c133
27 changes: 26 additions & 1 deletion Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Microsoft.Azure.Cosmos
{
using System;
using System.Security;
using System.Text;
using Microsoft.Azure.Cosmos.CosmosElements;
using Microsoft.Azure.Cosmos.Query;
Expand Down Expand Up @@ -50,7 +51,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; } = GetDefaultODEValue();

/// <summary>
/// Gets or sets the maximum number of items that can be buffered client side during
Expand Down Expand Up @@ -281,5 +282,29 @@ internal static void FillContinuationToken(
request.Headers.ContinuationToken = continuationToken;
}
}

/// <summary>
/// Returns the default value for ODE when QueryRequestOptions are initialized.
/// </summary>
/// <returns>If an environment variable named EnableOptimisticDirectExecution has as a boolean (true/false) value, it will be honored, otherwise default value of True</returns>
private static bool GetDefaultODEValue()
Comment thread
adityasa marked this conversation as resolved.
Outdated
{
string enableODEEnvironmentValue;
Comment thread
adityasa marked this conversation as resolved.
Outdated
try
{
enableODEEnvironmentValue = Environment.GetEnvironmentVariable(nameof(EnableOptimisticDirectExecution));
}
catch (SecurityException)
{
// Ignore permission failure in trying to retrieve the environment variable.
enableODEEnvironmentValue = null;
Comment thread
adityasa marked this conversation as resolved.
Outdated
}

bool defaultODEValue = (enableODEEnvironmentValue != null &&
bool.TryParse(enableODEEnvironmentValue, out bool environmentValue))
? environmentValue
: true;
return defaultODEValue;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,97 @@ 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()
{
try
{
QueryRequestOptions options = new QueryRequestOptions();
Assert.IsTrue(options.EnableOptimisticDirectExecution);

foreach ((string environmentVar, bool expectedVal) in new[]
{
("true", true),
("True", true),
("TRUE", true),
("truE", true),
("false", false),
("False", false),
("FALSE", false),
("false", false),
(null, true),
(string.Empty, true),
("", true),
("'", true),
("-", true),
("asdf", true),
})
{
Environment.SetEnvironmentVariable("EnableOptimisticDirectExecution", environmentVar);
QueryRequestOptions options2 = new QueryRequestOptions();
Assert.AreEqual(expectedVal, options2.EnableOptimisticDirectExecution, $"EnvironmentVariable:'{environmentVar}', expected:'{expectedVal}', actual:'{options2.EnableOptimisticDirectExecution}'");
}

await this.TestQueryExecutionUsingODEEnvironmentVariable(
environmentVariableValue: "false",
expectODEPipeline: false);

await this.TestQueryExecutionUsingODEEnvironmentVariable(
environmentVariableValue: "true",
expectODEPipeline: true);
}
finally
{
// Attempt to protect other ODE tests from side-effects in case of test failure.
Environment.SetEnvironmentVariable("EnableOptimisticDirectExecution", null);
}
}

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();

// Test query execution using environment variable
Environment.SetEnvironmentVariable("EnableOptimisticDirectExecution", 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);
}

private static async Task RunTests(IEnumerable<DirectExecutionTestCase> testCases, Container container)
Expand All @@ -567,9 +658,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 @@ -631,7 +726,7 @@ private static DirectExecutionTestCase CreateInput(
string query,
IReadOnlyList<int> expectedResult,
PartitionKey? partitionKey,
bool enableOptimisticDirectExecution,
bool? enableOptimisticDirectExecution,
int[] pageSizeOptions,
TestInjections.PipelineType expectedPipelineType)
{
Expand All @@ -643,15 +738,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