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

Query: Add Optimistic Direct Execution configuration override support on the Client #4122

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
085d7d5
Added ability to accept the AllowOptimisticDirectExecution flag from …
akotalwar Oct 13, 2023
9eda804
Added comment and removed extra spacing
akotalwar Oct 13, 2023
c054c51
Added test coverage
akotalwar Oct 13, 2023
076f345
Added exception handling logic
akotalwar Oct 15, 2023
5f29b91
Resolved comments
akotalwar Oct 20, 2023
2191de4
Added null check for key parameter
akotalwar Oct 23, 2023
61c3893
Removed changes to common test infra
akotalwar Oct 23, 2023
5d24481
Removed all changes from QueryPartitionProviderTestInstance
akotalwar Oct 24, 2023
cc01ca5
Remove changes pt2
akotalwar Oct 24, 2023
a46862f
Removed the dictionary in QueryPartitionProvider and added a bool ins…
akotalwar Oct 24, 2023
6a6e495
Updated GetClientDisableOptimisticDirectExecution()
akotalwar Oct 24, 2023
bdda380
Fixed comments
akotalwar Oct 26, 2023
5f9a2b6
Revert QueryIterator.cs
akotalwar Oct 26, 2023
5e0f682
Undoing changes to settings.json
akotalwar Oct 26, 2023
26dfda8
Undoing changes to QueryIterator.cs
akotalwar Oct 26, 2023
986c3a3
Updated error message
akotalwar Oct 26, 2023
a953803
Made functions static
akotalwar Oct 27, 2023
8d711ff
Cast to bool instead of recasting in GetClientDisableOptimisticDirect…
akotalwar Oct 27, 2023
35d6618
Fix merge conflicts
akotalwar Oct 27, 2023
459a4b9
Merge branch 'master' into users/akotalwar/ODEGatewayConfig
akotalwar Oct 27, 2023
f8cc146
Added ignore flag
akotalwar Dec 7, 2023
0ff09d7
Merge branch 'master' into users/akotalwar/ODEGatewayConfig
akotalwar Dec 7, 2023
ab3f46e
Fixed merge conflicts
akotalwar Dec 7, 2023
a591dff
Updated GetPartitionedQueryExecutionInfoAndPartitionProvider()
akotalwar Dec 7, 2023
4bafe39
Updated return type in OffsetLimitPageSize()
akotalwar Dec 11, 2023
78a1eb7
Merge branch 'master' into users/akotalwar/ODEGatewayConfig
akotalwar Dec 12, 2023
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 @@ -32,6 +32,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.ExecutionContext

internal static class CosmosQueryExecutionContextFactory
{
internal const string ClientDisableOptimisticDirectExecution = "clientDisableOptimisticDirectExecution";
private const string InternalPartitionKeyDefinitionProperty = "x-ms-query-partitionkey-definition";
private const string QueryInspectionPattern = @"\s+(GROUP\s+BY\s+|COUNT\s*\(|MIN\s*\(|MAX\s*\(|AVG\s*\(|SUM\s*\(|DISTINCT\s+)";
private const string OptimisticDirectExecution = "OptimisticDirectExecution";
Expand Down Expand Up @@ -250,9 +251,9 @@ private static async Task<TryCatch<IQueryPipelineStage>> TryCreateFromPartitione

TryCatch<IQueryPipelineStage> tryCreatePipelineStage;
Documents.PartitionKeyRange targetRange = await TryGetTargetRangeOptimisticDirectExecutionAsync(
inputParameters,
partitionedQueryExecutionInfo,
cosmosQueryContext,
inputParameters,
partitionedQueryExecutionInfo,
cosmosQueryContext,
containerQueryProperties,
trace);

Expand Down Expand Up @@ -761,13 +762,18 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP
ContainerQueryProperties containerQueryProperties,
ITrace trace)
{
if (!inputParameters.EnableOptimisticDirectExecution)
bool clientDisableOptimisticDirectExecution = await cosmosQueryContext.QueryClient.GetClientDisableOptimisticDirectExecutionAsync();

// Use the Ode code path only if ClientDisableOptimisticDirectExecution is false and EnableOptimisticDirectExecution is true
if (clientDisableOptimisticDirectExecution || !inputParameters.EnableOptimisticDirectExecution)
{
if (inputParameters.InitialUserContinuationToken != null
&& OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken))
if (inputParameters.InitialUserContinuationToken != null
&& OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken))
{
throw new MalformedContinuationTokenException($"The continuation token supplied requires the Optimistic Direct Execution flag to be enabled in QueryRequestOptions for the query execution to resume. " +
$"{inputParameters.InitialUserContinuationToken}");
string errorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " +
"If the error persists after that, contact system administrator.";

throw new MalformedContinuationTokenException($"{errorMessage} Continuation Token: {inputParameters.InitialUserContinuationToken}");
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ public abstract Task<TryCatch<QueryPage>> ExecuteItemQueryAsync(
ITrace trace,
CancellationToken cancellationToken);

public abstract Task<bool> GetClientDisableOptimisticDirectExecutionAsync();

public abstract Task<PartitionedQueryExecutionInfo> ExecuteQueryPlanRequestAsync(
string resourceUri,
Documents.ResourceType resourceType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.QueryPlan
using System.Text;
using Microsoft.Azure.Cosmos.Core.Trace;
using Microsoft.Azure.Cosmos.Query.Core.Exceptions;
using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext;
using Microsoft.Azure.Cosmos.Query.Core.Monads;
using Microsoft.Azure.Cosmos.Routing;
using Microsoft.Azure.Cosmos.Tracing;
Expand Down Expand Up @@ -46,6 +47,9 @@ internal sealed class QueryPartitionProvider : IDisposable
private bool disposed;
private string queryengineConfiguration;

// TODO: Move this into a config class of its own
public bool ClientDisableOptimisticDirectExecution { get; private set; }
akotalwar marked this conversation as resolved.
Show resolved Hide resolved

public QueryPartitionProvider(IDictionary<string, object> queryengineConfiguration)
{
if (queryengineConfiguration == null)
Expand All @@ -60,6 +64,7 @@ public QueryPartitionProvider(IDictionary<string, object> queryengineConfigurati

this.disposed = false;
this.queryengineConfiguration = JsonConvert.SerializeObject(queryengineConfiguration);
this.ClientDisableOptimisticDirectExecution = GetClientDisableOptimisticDirectExecution((IReadOnlyDictionary<string, object>)queryengineConfiguration);
this.serviceProvider = IntPtr.Zero;

this.serviceProviderStateLock = new object();
Expand Down Expand Up @@ -92,6 +97,7 @@ public void Update(IDictionary<string, object> queryengineConfiguration)
if (!string.Equals(this.queryengineConfiguration, newConfiguration))
{
this.queryengineConfiguration = newConfiguration;
this.ClientDisableOptimisticDirectExecution = GetClientDisableOptimisticDirectExecution((IReadOnlyDictionary<string, object>)queryengineConfiguration);

if (!this.disposed && this.serviceProvider != IntPtr.Zero)
{
Expand Down Expand Up @@ -132,6 +138,7 @@ public TryCatch<PartitionedQueryExecutionInfo> TryGetPartitionedQueryExecutionIn
allowDCount: allowDCount,
useSystemPrefix: useSystemPrefix,
geospatialType: geospatialType);

if (!tryGetInternalQueryInfo.Succeeded)
{
return TryCatch<PartitionedQueryExecutionInfo>.FromException(tryGetInternalQueryInfo.Exception);
Expand All @@ -141,6 +148,16 @@ public TryCatch<PartitionedQueryExecutionInfo> TryGetPartitionedQueryExecutionIn
return TryCatch<PartitionedQueryExecutionInfo>.FromResult(queryInfo);
}

private static bool GetClientDisableOptimisticDirectExecution(IReadOnlyDictionary<string, object> queryengineConfiguration)
{
if (queryengineConfiguration.TryGetValue(CosmosQueryExecutionContextFactory.ClientDisableOptimisticDirectExecution, out object queryConfigProperty))
{
return (bool)queryConfigProperty;
}

return false;
}

internal PartitionedQueryExecutionInfo ConvertPartitionedQueryExecutionInfo(
PartitionedQueryExecutionInfoInternal queryInfoInternal,
PartitionKeyDefinition partitionKeyDefinition)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ public override async Task<PartitionedQueryExecutionInfo> ExecuteQueryPlanReques
return partitionedQueryExecutionInfo;
}

public override async Task<bool> GetClientDisableOptimisticDirectExecutionAsync()
{
QueryPartitionProvider provider = await this.clientContext.DocumentClient.QueryPartitionProvider;
return provider.ClientDisableOptimisticDirectExecution;
}

public override async Task<List<PartitionKeyRange>> GetTargetPartitionKeyRangeByFeedRangeAsync(
string resourceLink,
string collectionResourceId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public sealed class OptimisticDirectExecutionQueryTests : QueryTestsBase
private const string PartitionKeyField = "key";
private const string NumberField = "numberField";
private const string NullField = "nullField";
private const string ClientDisableOptimisticDirectExecution = "clientDisableOptimisticDirectExecution";

private static class PageSizeOptions
{
Expand Down Expand Up @@ -538,6 +539,22 @@ await this.CreateIngestQueryDeleteAsync(
documents,
(container, documents) => RunFailingTests(container, invalidQueries),
"/" + PartitionKeyField);
}

//TODO: Remove Ignore flag once emulator is updated to 1101
[Ignore]
[TestMethod]
public async Task TestClientDisableOdeDefaultValue()
{
string authKey = Utils.ConfigurationManager.AppSettings["MasterKey"];
string endpoint = Utils.ConfigurationManager.AppSettings["GatewayEndpoint"];

CosmosClient client = new CosmosClient($"AccountEndpoint={endpoint};AccountKey={authKey}");
AccountProperties properties = await client.ReadAccountAsync();

bool success = bool.TryParse(properties.QueryEngineConfiguration[ClientDisableOptimisticDirectExecution].ToString(), out bool clientDisablOde);
Assert.IsTrue(success, $"Parsing must succeed. Value supplied '{ClientDisableOptimisticDirectExecution}'");
Assert.IsFalse(clientDisablOde);
}

private static async Task RunTests(IEnumerable<DirectExecutionTestCase> testCases, Container container)
Expand Down
Loading
Loading