Skip to content

Commit

Permalink
[Internal] LocalQuorum: Refactors override (i.e. strong) to allow fro…
Browse files Browse the repository at this point in the history
…m any account consistency (#3753)

- Localquorum override (i.e. strong) to allow from any account consistency
- Facilitates no-downtime downgrade of existing accounts (i.e. existing Strong/bounded accounts migration to Eventual)
  • Loading branch information
kirankumarkolli authored and ealsur committed Mar 13, 2023
1 parent 45c0d14 commit d8b2333
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 51 deletions.
9 changes: 1 addition & 8 deletions Microsoft.Azure.Cosmos/src/ValidationHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ public static bool IsValidConsistencyLevelOverwrite(
{
if (isLocalQuorumConsistency &&
ValidationHelpers.IsLocalQuorumConsistency(
backendConsistency: backendConsistency,
desiredConsistency: desiredConsistency,
operationType: operationType,
resourceType: resourceType))
Expand Down Expand Up @@ -109,21 +108,15 @@ private static bool IsValidConsistencyLevelOverwrite(
/// <summary>
/// Condition to check Quorum(i.e. Strong) read with either an eventual consistency account or a consistent prefix account.
/// </summary>
/// <param name="backendConsistency"></param>
/// <param name="desiredConsistency"></param>
/// <param name="operationType"></param>
/// <param name="resourceType"></param>
/// <returns>true/false</returns>
private static bool IsLocalQuorumConsistency(Documents.ConsistencyLevel backendConsistency,
private static bool IsLocalQuorumConsistency(
Documents.ConsistencyLevel desiredConsistency,
OperationType? operationType,
ResourceType? resourceType)
{
if (backendConsistency != Documents.ConsistencyLevel.Eventual && backendConsistency != Documents.ConsistencyLevel.ConsistentPrefix)
{
return false;
}

if (desiredConsistency != Documents.ConsistencyLevel.Strong)
{
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,69 +4,81 @@

namespace Microsoft.Azure.Cosmos.Tests
{
using System;
using System.Collections.Generic;
using System.Data;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[TestClass]
public class ValidationHelpersTest
{
[TestMethod]
[DataRow(true, ConsistencyLevel.Eventual, ConsistencyLevel.Strong)]
[DataRow(true, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong)]
[DataRow(false, ConsistencyLevel.Eventual, ConsistencyLevel.BoundedStaleness)]
[DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.BoundedStaleness)]
[DataRow(false, ConsistencyLevel.Session, ConsistencyLevel.Strong)]
[DataRow(false, ConsistencyLevel.BoundedStaleness, ConsistencyLevel.Strong)]
public void TestIsValidConsistencyLevelOverwrite(bool isValidConsistencyLevelOverwrite,
ConsistencyLevel backendConsistencyLevel,
ConsistencyLevel desiredConsistencyLevel)
[DataRow(true)]
[DataRow(false)]
public void TestIsValidConsistencyLevelOverwrite_AllCombinations(
bool isValidConsistencyLevelOverwrite)
{
bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel,
desiredConsistencyLevel,
true,
Documents.OperationType.Read,
Documents.ResourceType.Document);
ConsistencyLevel[] allConsistencies = Enum.GetValues<ConsistencyLevel>();

// All overrides when target is 'Strong' are VALID
ConsistencyLevel desiredConsistencyLevel = ConsistencyLevel.Strong;
foreach (ConsistencyLevel backendConsistencyLevel in allConsistencies)
{
if (backendConsistencyLevel == desiredConsistencyLevel)
{
continue;
}

foreach (KeyValuePair<Documents.OperationType, bool> entry in ValidationHelpersTest.GetPerOperationExpectations())
{
bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel,
desiredConsistencyLevel,
isValidConsistencyLevelOverwrite,
(Documents.OperationType)entry.Key,
Documents.ResourceType.Document);

Assert.AreEqual(isValidConsistencyLevelOverwrite, result);
Assert.AreEqual(isValidConsistencyLevelOverwrite && entry.Value, result,
$"({isValidConsistencyLevelOverwrite}, {backendConsistencyLevel}, {desiredConsistencyLevel}) ({entry.Key}, {entry.Value})");
}
}
}

[TestMethod]
[DataRow(false, ConsistencyLevel.Eventual, ConsistencyLevel.Strong)]
[DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong)]
public void TestIsValidConsistencyLevelOverwrite_OnlyWhenSpecifyingExplicitOverwrite(bool isValidConsistencyLevelOverwrite,
[DataRow(ConsistencyLevel.Eventual, ConsistencyLevel.BoundedStaleness)]
[DataRow(ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.BoundedStaleness)]
[DataRow(ConsistencyLevel.Session, ConsistencyLevel.BoundedStaleness)]
public void TestIsValidConsistencyLevelOverwrite_BoundedPromotionsRejected(
ConsistencyLevel backendConsistencyLevel,
ConsistencyLevel desiredConsistencyLevel)
{
bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel,
desiredConsistencyLevel,
false,
Documents.OperationType.Read,
Documents.ResourceType.Document);
foreach (KeyValuePair<Documents.OperationType, bool> entry in ValidationHelpersTest.GetPerOperationExpectations())
{
bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel,
desiredConsistencyLevel,
true,
(Documents.OperationType)entry.Key,
Documents.ResourceType.Document);

Assert.AreEqual(isValidConsistencyLevelOverwrite, result);
Assert.AreEqual(false, result,
$"({backendConsistencyLevel}, {desiredConsistencyLevel}) ({entry.Key}, {entry.Value})");
}
}

[TestMethod]
[DataRow(true, ConsistencyLevel.Eventual, ConsistencyLevel.Strong, Documents.OperationType.Read)]
[DataRow(true, ConsistencyLevel.Eventual, ConsistencyLevel.Strong, Documents.OperationType.ReadFeed)]
[DataRow(true, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.Query)]
[DataRow(true, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.SqlQuery)]
[DataRow(false, ConsistencyLevel.Eventual, ConsistencyLevel.Strong, Documents.OperationType.QueryPlan)]
[DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.Create)]
[DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.Batch)]
public void TestIsValidConsistencyLevelOverwrite_OnlyAllowedForCertainOperationTypes(
bool isValidConsistencyLevelOverwrite,
ConsistencyLevel backendConsistencyLevel,
ConsistencyLevel desiredConsistencyLevel,
dynamic operationType)
private static Dictionary<Documents.OperationType, bool> GetPerOperationExpectations()
{
bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel,
desiredConsistencyLevel,
true,
(Documents.OperationType) operationType,
Documents.ResourceType.Document);
Dictionary<Documents.OperationType, bool> perOperationOverride = new Dictionary<Documents.OperationType, bool>();

foreach (Documents.OperationType operationType in Enum.GetValues<Documents.OperationType>())
{
perOperationOverride.Add(
operationType,
Documents.OperationTypeExtensions.IsReadOperation(operationType)
&& operationType != Documents.OperationType.Head
&& operationType != Documents.OperationType.HeadFeed
&& operationType != Documents.OperationType.QueryPlan);
}

Assert.AreEqual(isValidConsistencyLevelOverwrite, result);
return perOperationOverride;
}
}
}

0 comments on commit d8b2333

Please sign in to comment.