diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md index 1ebb710197..995be2decf 100644 --- a/BUILDGUIDE.md +++ b/BUILDGUIDE.md @@ -245,12 +245,6 @@ Scaled decimal parameter truncation can be enabled by enabling the below AppCont **"Switch.Microsoft.Data.SqlClient.TruncateScaledDecimal"** -## Enabling configurable retry logic - -To use this feature, you must enable the following AppContext switch at application startup: - -**"Switch.Microsoft.Data.SqlClient.EnableRetryLogic"** - ## Enabling row version null behavior `SqlDataReader` returns a `DBNull` value instead of an empty `byte[]`. To enable the legacy behavior, you must enable the following AppContext switch on application startup: diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs index 5329d1ff08..5eea21049c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -506,7 +506,7 @@ private SqlInternalConnectionTds InternalTdsConnection } } - private static bool IsRetryEnabled => LocalAppContextSwitches.IsRetryEnabled; + private bool IsProviderRetriable => SqlConfigurableRetryFactory.IsRetriable(RetryLogicProvider); /// [Browsable(false)] @@ -1101,7 +1101,7 @@ public override object ExecuteScalar() statistics = SqlStatistics.StartTimer(Statistics); WriteBeginExecuteEvent(); SqlDataReader ds; - ds = IsRetryEnabled ? + ds = IsProviderRetriable ? RunExecuteReaderWithRetry(0, RunBehavior.ReturnImmediately, returnStream: true) : RunExecuteReader(0, RunBehavior.ReturnImmediately, returnStream: true, method: nameof(ExecuteScalar)); success = true; @@ -1192,7 +1192,7 @@ public override int ExecuteNonQuery() { statistics = SqlStatistics.StartTimer(Statistics); WriteBeginExecuteEvent(); - if (IsRetryEnabled) + if (IsProviderRetriable) { InternalExecuteNonQueryWithRetry(sendToPipe: false, timeout: CommandTimeout, out _, asyncWrite: false, inRetry: false); } @@ -1706,7 +1706,7 @@ public XmlReader ExecuteXmlReader() WriteBeginExecuteEvent(); // use the reader to consume metadata SqlDataReader ds; - ds = IsRetryEnabled ? + ds = IsProviderRetriable ? RunExecuteReaderWithRetry(CommandBehavior.SequentialAccess, RunBehavior.ReturnImmediately, returnStream: true) : RunExecuteReader(CommandBehavior.SequentialAccess, RunBehavior.ReturnImmediately, returnStream: true); success = true; @@ -2043,7 +2043,7 @@ protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) { WriteBeginExecuteEvent(); statistics = SqlStatistics.StartTimer(Statistics); - return IsRetryEnabled ? + return IsProviderRetriable ? RunExecuteReaderWithRetry(behavior, RunBehavior.ReturnImmediately, returnStream: true) : RunExecuteReader(behavior, RunBehavior.ReturnImmediately, returnStream: true); } @@ -2548,7 +2548,7 @@ private SqlDataReader InternalEndExecuteReader(IAsyncResult asyncResult, bool is /// public override Task ExecuteNonQueryAsync(CancellationToken cancellationToken) - => IsRetryEnabled ? + => IsProviderRetriable ? InternalExecuteNonQueryWithRetryAsync(cancellationToken) : InternalExecuteNonQueryAsync(cancellationToken); @@ -2648,7 +2648,7 @@ protected override Task ExecuteDbDataReaderAsync(CommandBehavior b /// new public Task ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) - => IsRetryEnabled ? + => IsProviderRetriable ? InternalExecuteReaderWithRetryAsync(behavior, cancellationToken) : InternalExecuteReaderAsync(behavior, cancellationToken); @@ -2821,7 +2821,7 @@ public Task ExecuteXmlReaderAsync() /// public Task ExecuteXmlReaderAsync(CancellationToken cancellationToken) - => IsRetryEnabled ? + => IsProviderRetriable ? InternalExecuteXmlReaderWithRetryAsync(cancellationToken) : InternalExecuteXmlReaderAsync(cancellationToken); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs index f4594d3ca4..abad0809cb 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs @@ -114,7 +114,7 @@ private static readonly ConcurrentDictionary> _ColumnEncry private static readonly Action s_openAsyncCancel = OpenAsyncCancel; private static readonly Action, object> s_openAsyncComplete = OpenAsyncComplete; - private static bool IsRetryEnabled => LocalAppContextSwitches.IsRetryEnabled; + private bool IsProviderRetriable => SqlConfigurableRetryFactory.IsRetriable(RetryLogicProvider); /// [Browsable(false)] @@ -1324,7 +1324,7 @@ public void Open(SqlConnectionOverrides overrides) try { statistics = SqlStatistics.StartTimer(Statistics); - if (!(IsRetryEnabled ? TryOpenWithRetry(null, overrides) : TryOpen(null, overrides))) + if (!(IsProviderRetriable ? TryOpenWithRetry(null, overrides) : TryOpen(null, overrides))) { throw ADP.InternalError(ADP.InternalErrorCode.SynchronousConnectReturnedPending); } @@ -1575,7 +1575,7 @@ private Task InternalOpenWithRetryAsync(CancellationToken cancellationToken) /// public override Task OpenAsync(CancellationToken cancellationToken) - => IsRetryEnabled ? + => IsProviderRetriable ? InternalOpenWithRetryAsync(cancellationToken) : InternalOpenAsync(cancellationToken); diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs index 774ee07582..3b19b60ab9 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -620,7 +620,7 @@ private bool IsShiloh } } - private static bool IsRetryEnabled => LocalAppContextSwitches.IsRetryEnabled; + private bool IsProviderRetriable => SqlConfigurableRetryFactory.IsRetriable(RetryLogicProvider); /// [ @@ -1382,7 +1382,7 @@ public override object ExecuteScalar() statistics = SqlStatistics.StartTimer(Statistics); WriteBeginExecuteEvent(); SqlDataReader ds; - ds = IsRetryEnabled ? + ds = IsProviderRetriable ? RunExecuteReaderWithRetry(0, RunBehavior.ReturnImmediately, true, ADP.ExecuteScalar) : RunExecuteReader(0, RunBehavior.ReturnImmediately, true, ADP.ExecuteScalar); object result = CompleteExecuteScalar(ds, false); @@ -1462,7 +1462,7 @@ public override int ExecuteNonQuery() statistics = SqlStatistics.StartTimer(Statistics); WriteBeginExecuteEvent(); bool usedCache; - if (IsRetryEnabled) + if (IsProviderRetriable) { InternalExecuteNonQueryWithRetry(ADP.ExecuteNonQuery, sendToPipe: false, CommandTimeout, out usedCache, asyncWrite: false, inRetry: false); } @@ -2098,7 +2098,7 @@ public XmlReader ExecuteXmlReader() // use the reader to consume metadata SqlDataReader ds; - ds = IsRetryEnabled ? + ds = IsProviderRetriable ? RunExecuteReaderWithRetry(CommandBehavior.SequentialAccess, RunBehavior.ReturnImmediately, true, ADP.ExecuteXmlReader) : RunExecuteReader(CommandBehavior.SequentialAccess, RunBehavior.ReturnImmediately, true, ADP.ExecuteXmlReader); XmlReader result = CompleteXmlReader(ds); @@ -2426,7 +2426,7 @@ private SqlDataReader ExecuteReaderWithRetry(CommandBehavior behavior, string me try { statistics = SqlStatistics.StartTimer(Statistics); - return IsRetryEnabled ? + return IsProviderRetriable ? ExecuteReaderWithRetry(CommandBehavior.Default, ADP.ExecuteReader) : ExecuteReader(CommandBehavior.Default, ADP.ExecuteReader); } @@ -2444,7 +2444,7 @@ private SqlDataReader ExecuteReaderWithRetry(CommandBehavior behavior, string me { SqlClientEventSource.Log.TryCorrelationTraceEvent(" ObjectID {0}, behavior={1}, ActivityID {2}", ObjectID, (int)behavior, ActivityCorrelator.Current); - return IsRetryEnabled ? + return IsProviderRetriable ? ExecuteReaderWithRetry(behavior, ADP.ExecuteReader) : ExecuteReader(behavior, ADP.ExecuteReader); } @@ -2960,7 +2960,7 @@ private Task InternalExecuteNonQueryWithRetryAsync(CancellationToken cancel /// public override Task ExecuteNonQueryAsync(CancellationToken cancellationToken) - => IsRetryEnabled ? + => IsProviderRetriable ? InternalExecuteNonQueryWithRetryAsync(cancellationToken) : InternalExecuteNonQueryAsync(cancellationToken); @@ -3039,25 +3039,25 @@ private Task InternalExecuteReaderWithRetryAsync(CommandBehavior /// new public Task ExecuteReaderAsync() - => IsRetryEnabled ? + => IsProviderRetriable ? InternalExecuteReaderWithRetryAsync(CommandBehavior.Default, CancellationToken.None) : InternalExecuteReaderAsync(CommandBehavior.Default, CancellationToken.None); /// new public Task ExecuteReaderAsync(CommandBehavior behavior) - => IsRetryEnabled ? + => IsProviderRetriable ? InternalExecuteReaderWithRetryAsync(behavior, CancellationToken.None) : InternalExecuteReaderAsync(behavior, CancellationToken.None); /// new public Task ExecuteReaderAsync(CancellationToken cancellationToken) - => IsRetryEnabled ? + => IsProviderRetriable ? InternalExecuteReaderWithRetryAsync(CommandBehavior.Default, cancellationToken) : InternalExecuteReaderAsync(CommandBehavior.Default, cancellationToken); /// new public Task ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) - => IsRetryEnabled ? + => IsProviderRetriable ? InternalExecuteReaderWithRetryAsync(behavior, cancellationToken) : InternalExecuteReaderAsync(behavior, cancellationToken); @@ -3203,7 +3203,7 @@ private Task InternalExecuteXmlReaderWithRetryAsync(CancellationToken /// public Task ExecuteXmlReaderAsync(CancellationToken cancellationToken) - => IsRetryEnabled ? + => IsProviderRetriable ? InternalExecuteXmlReaderWithRetryAsync(cancellationToken) : InternalExecuteXmlReaderAsync(cancellationToken); diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs index a22071b5ca..45e6c7390d 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnection.cs @@ -310,7 +310,7 @@ internal List GetColumnEncryptionCustomKeyStoreProvidersNames() // Retry Logic private SqlRetryLogicBaseProvider _retryLogicProvider; - private static bool IsRetryEnabled => LocalAppContextSwitches.IsRetryEnabled; + private bool IsProviderRetriable => SqlConfigurableRetryFactory.IsRetriable(RetryLogicProvider); /// [ @@ -1648,7 +1648,7 @@ public void Open(SqlConnectionOverrides overrides) { statistics = SqlStatistics.StartTimer(Statistics); - if (!(IsRetryEnabled ? TryOpenWithRetry(null, overrides) : TryOpen(null, overrides))) + if (!(IsProviderRetriable ? TryOpenWithRetry(null, overrides) : TryOpen(null, overrides))) { throw ADP.InternalError(ADP.InternalErrorCode.SynchronousConnectReturnedPending); } @@ -1882,7 +1882,7 @@ private Task InternalOpenWithRetryAsync(CancellationToken cancellationToken) /// public override Task OpenAsync(CancellationToken cancellationToken) - => IsRetryEnabled ? + => IsProviderRetriable ? InternalOpenWithRetryAsync(cancellationToken) : InternalOpenAsync(cancellationToken); diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs index c0947e5854..c0d7295944 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/LocalAppContextSwitches.cs @@ -14,13 +14,10 @@ internal static partial class LocalAppContextSwitches internal const string MakeReadAsyncBlockingString = @"Switch.Microsoft.Data.SqlClient.MakeReadAsyncBlocking"; internal const string LegacyRowVersionNullString = @"Switch.Microsoft.Data.SqlClient.LegacyRowVersionNullBehavior"; internal const string UseSystemDefaultSecureProtocolsString = @"Switch.Microsoft.Data.SqlClient.UseSystemDefaultSecureProtocols"; - // safety switch - internal const string EnableRetryLogicSwitch = "Switch.Microsoft.Data.SqlClient.EnableRetryLogic"; private static bool _makeReadAsyncBlocking; private static bool? s_LegacyRowVersionNullBehavior; private static bool? s_UseSystemDefaultSecureProtocols; - private static bool? s_isRetryEnabled = null; #if !NETFRAMEWORK static LocalAppContextSwitches() @@ -38,20 +35,6 @@ static LocalAppContextSwitches() } #endif - internal static bool IsRetryEnabled - { - get - { - if (s_isRetryEnabled is null) - { - bool result; - result = AppContext.TryGetSwitch(EnableRetryLogicSwitch, out result) ? result : false; - s_isRetryEnabled = result; - } - return s_isRetryEnabled.Value; - } - } - public static bool MakeReadAsyncBlocking { [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Reliability/SqlConfigurableRetryFactory.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Reliability/SqlConfigurableRetryFactory.cs index 63fd370901..81c0597ea9 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Reliability/SqlConfigurableRetryFactory.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Reliability/SqlConfigurableRetryFactory.cs @@ -101,6 +101,12 @@ public static SqlRetryLogicBaseProvider CreateNoneRetryProvider() return new SqlRetryLogicProvider(retryLogic); } + /// + /// Verifies the provider which is not null and doesn't include SqlNoneIntervalEnumerator enumerator object. + /// + internal static bool IsRetriable(SqlRetryLogicBaseProvider provider) + => provider is not null && (provider.RetryLogic is null || provider.RetryLogic.RetryIntervalEnumerator is not SqlNoneIntervalEnumerator); + /// Return true if the exception is a transient fault. private static bool TransientErrorsCondition(Exception e, IEnumerable retriableConditions) { diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicConfigHelper.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicConfigHelper.cs index 07714d49f9..7162c4dcaa 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicConfigHelper.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicConfigHelper.cs @@ -91,13 +91,8 @@ public static SqlRetryLogicBaseProvider GetConnectionProvider(object loader) public static SqlRetryLogicBaseProvider GetCommandProvider(object loader) => GetValue(loader, s_configurationLoaderType, "CommandProvider"); - public static void AssessProvider(SqlRetryLogicBaseProvider provider, RetryLogicConfigs option, bool switchValue) - { - AssessRetryLogic(provider.RetryLogic, option); - - AppContext.TryGetSwitch(RetryLogicTestHelper.RetryAppContextSwitch, out bool value); - Assert.Equal(switchValue, value); - } + public static void AssessProvider(SqlRetryLogicBaseProvider provider, RetryLogicConfigs option) + => AssessRetryLogic(provider.RetryLogic, option); public static void AssessRetryLogic(SqlRetryLogicBase retryLogic, RetryLogicConfigs option) { @@ -142,9 +137,8 @@ public static IEnumerable GetIivalidTimes() } } - public static object ReturnLoaderAndProviders(RetryLogicConfigs cnnCfg, RetryLogicConfigs cmdCfg, bool switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider) + public static object ReturnLoaderAndProviders(RetryLogicConfigs cnnCfg, RetryLogicConfigs cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider) { - ApplyContextSwitchByManager(RetryLogicTestHelper.RetryAppContextSwitch, switchValue); var loaderObj = CreateLoader(cnnCfg, cmdCfg); cnnProvider = GetConnectionProvider(loaderObj); cmdProvider = GetCommandProvider(loaderObj); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicCounterTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicCounterTest.cs index 86f53151bd..b62f2f1f53 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicCounterTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicCounterTest.cs @@ -24,8 +24,6 @@ public async void ValidateRetryCount_SqlCommand_Async(string methodName, int num try { - RetryLogicTestHelper.SetRetrySwitch(true); - using var connection = new SqlConnection(DataTestUtility.TCPConnectionString); connection.Open(); @@ -61,10 +59,6 @@ public async void ValidateRetryCount_SqlCommand_Async(string methodName, int num { Assert.Equal(numOfTries, _errorInfoRetryProvider.CallCounter); } - finally - { - RetryLogicTestHelper.SetRetrySwitch(false); - } } [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] @@ -80,8 +74,6 @@ public void ValidateRetryCount_SqlCommand_Sync(string methodName, int numOfTries try { - RetryLogicTestHelper.SetRetrySwitch(true); - using var connection = new SqlConnection(DataTestUtility.TCPConnectionString); connection.Open(); @@ -117,10 +109,6 @@ public void ValidateRetryCount_SqlCommand_Sync(string methodName, int numOfTries { Assert.Equal(numOfTries, _errorInfoRetryProvider.CallCounter); } - finally - { - RetryLogicTestHelper.SetRetrySwitch(false); - } } public class ErrorInfoRetryLogicProvider : SqlRetryLogicBaseProvider diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicTestHelper.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicTestHelper.cs index 3a943461ee..d72c9f3d4c 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicTestHelper.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicTestHelper.cs @@ -45,11 +45,6 @@ public enum FilterSqlStatements public class RetryLogicTestHelper { - internal const string RetryAppContextSwitch = "Switch.Microsoft.Data.SqlClient.EnableRetryLogic"; - private static readonly Assembly s_sqlClientAssembly = typeof(SqlConnection).Assembly; - private static readonly Type s_LocalAppContextSwitchesType = s_sqlClientAssembly.GetType("Microsoft.Data.SqlClient.LocalAppContextSwitches"); - private static readonly FieldInfo s_isRetryEnabledFieldInfo = s_LocalAppContextSwitchesType.GetField("s_isRetryEnabled", BindingFlags.Static | BindingFlags.NonPublic); - private static readonly HashSet s_defaultTransientErrors = new HashSet { @@ -83,14 +78,6 @@ private static readonly HashSet s_defaultTransientErrors internal static readonly string s_ExceedErrMsgPattern = SystemDataResourceManager.Instance.SqlRetryLogic_RetryExceeded; internal static readonly string s_CancelErrMsgPattern = SystemDataResourceManager.Instance.SqlRetryLogic_RetryCanceled; - public static void CleanRetryEnabledCache() => s_isRetryEnabledFieldInfo.SetValue(null, null); - - public static void SetRetrySwitch(bool value) - { - CleanRetryEnabledCache(); - AppContext.SetSwitch(RetryAppContextSwitch, value); - } - public static IEnumerable GetConnectionStrings() { var builder = new SqlConnectionStringBuilder(); @@ -114,8 +101,6 @@ public static IEnumerable GetConnectionAndRetryStrategy(int numberOfRe int deltaTimeMillisecond = 10, bool custom = true) { - SetRetrySwitch(true); - var option = new SqlRetryLogicOption() { NumberOfTries = numberOfRetries, @@ -165,22 +150,8 @@ public static IEnumerable GetConnectionAndRetryStrategyLockedTable(int public static IEnumerable GetNoneRetriableCondition() { - RetryLogicTestHelper.SetRetrySwitch(true); yield return new object[] { DataTestUtility.TCPConnectionString, null}; yield return new object[] { DataTestUtility.TCPConnectionString, SqlConfigurableRetryFactory.CreateNoneRetryProvider()}; - - RetryLogicTestHelper.SetRetrySwitch(false); - yield return new object[] { DataTestUtility.TCPConnectionString, null}; - yield return new object[] { DataTestUtility.TCPConnectionString, SqlConfigurableRetryFactory.CreateNoneRetryProvider()}; - - var option = new SqlRetryLogicOption() - { - NumberOfTries = 2, - DeltaTime = TimeSpan.FromMilliseconds(10), - MaxTimeInterval = TimeSpan.FromSeconds(2) - }; - foreach (var provider in GetRetryStrategies(option)) - yield return new object[] { DataTestUtility.TCPConnectionString, provider[0]}; } private static IEnumerable GetRetryStrategies(SqlRetryLogicOption retryLogicOption) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConfigurationManagerReliabilityTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConfigurationManagerReliabilityTest.cs index f5594069cf..a5e3f901d4 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConfigurationManagerReliabilityTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConfigurationManagerReliabilityTest.cs @@ -27,10 +27,8 @@ public class SqlConfigurationManagerReliabilityTest [InlineData(RetryLogicConfigHelper.RetryMethodName_Fix, RetryLogicConfigHelper.RetryMethodName_Inc)] [InlineData(RetryLogicConfigHelper.RetryMethodName_Inc, RetryLogicConfigHelper.RetryMethodName_Exp)] [InlineData(RetryLogicConfigHelper.RetryMethodName_Exp, RetryLogicConfigHelper.RetryMethodName_Fix)] - public void LoadValidInternalTypesAndEnableSwitch(string method1, string method2) + public void LoadValidInternalTypes(string method1, string method2) { - bool switchValue = true; - RetryLogicConfigs cnnCfg = RetryLogicConfigHelper.CreateRandomConfig(method1); RetryLogicConfigs cmdCfg = RetryLogicConfigHelper.CreateRandomConfig(method2, // Doesn't accept DML statements @@ -39,13 +37,12 @@ public void LoadValidInternalTypesAndEnableSwitch(string method1, string method2 cnnCfg.NumberOfTries = 1; cmdCfg.NumberOfTries = 1; - object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); + object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); Assert.NotNull(loaderObj); - RetryLogicConfigHelper.AssessProvider(cnnProvider, cnnCfg, switchValue); - RetryLogicConfigHelper.AssessProvider(cmdProvider, cmdCfg, switchValue); + RetryLogicConfigHelper.AssessProvider(cnnProvider, cnnCfg); + RetryLogicConfigHelper.AssessProvider(cmdProvider, cmdCfg); // check the retry in action - RetryLogicTestHelper.CleanRetryEnabledCache(); s_connectionCRLTest.ConnectionRetryOpenInvalidCatalogFailed(TcpCnnString, cnnProvider); s_commandCRLTest.RetryExecuteFail(TcpCnnString, cmdProvider); if (DataTestUtility.IsNotAzureSynapse()) @@ -53,26 +50,6 @@ public void LoadValidInternalTypesAndEnableSwitch(string method1, string method2 s_commandCRLTest.RetryExecuteUnauthorizedSqlStatementDML(TcpCnnString, cmdProvider); } } - - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [InlineData(RetryLogicConfigHelper.RetryMethodName_Fix, RetryLogicConfigHelper.RetryMethodName_Inc)] - [InlineData(RetryLogicConfigHelper.RetryMethodName_Inc, RetryLogicConfigHelper.RetryMethodName_Exp)] - [InlineData(RetryLogicConfigHelper.RetryMethodName_Exp, RetryLogicConfigHelper.RetryMethodName_Fix)] - public void LoadValidInternalTypesWithoutEnablingSwitch(string method1, string method2) - { - bool switchValue = false; - RetryLogicConfigs cnnCfg = RetryLogicConfigHelper.CreateRandomConfig(method1); - RetryLogicConfigs cmdCfg = RetryLogicConfigHelper.CreateRandomConfig(method2, @"Don't care!"); - - object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); - Assert.NotNull(loaderObj); - RetryLogicConfigHelper.AssessProvider(cnnProvider, cnnCfg, switchValue); - RetryLogicConfigHelper.AssessProvider(cmdProvider, cmdCfg, switchValue); - - RetryLogicTestHelper.CleanRetryEnabledCache(); - s_connectionCRLTest.DefaultOpenWithoutRetry(TcpCnnString, cnnProvider); - s_commandCRLTest.NoneRetriableExecuteFail(TcpCnnString, cmdProvider); - } #endregion #region External Functions @@ -86,8 +63,6 @@ public void LoadValidInternalTypesWithoutEnablingSwitch(string method1, string m [InlineData("Microsoft.Data.SqlClient.Tests.CustomConfigurableRetryLogicEx, ExternalConfigurableRetryLogic", "GetDefaultRetry")] public void LoadCustomMethod(string typeName, string methodName) { - bool switchValue = true; - RetryLogicConfigs cnnCfg = RetryLogicConfigHelper.CreateRandomConfig(methodName); RetryLogicConfigs cmdCfg = RetryLogicConfigHelper.CreateRandomConfig(methodName); // for sake of reducing the retry time in total @@ -97,10 +72,9 @@ public void LoadCustomMethod(string typeName, string methodName) cnnCfg.NumberOfTries = 1; cmdCfg.NumberOfTries = 3; - object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); + object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); Assert.NotNull(loaderObj); - RetryLogicTestHelper.CleanRetryEnabledCache(); TestConnection(cnnProvider, cnnCfg); TestCommandExecute(cmdProvider, cmdCfg); TestCommandExecuteAsync(cmdProvider, cmdCfg).Wait(); @@ -119,8 +93,6 @@ public void LoadCustomMethod(string typeName, string methodName) [InlineData("Microsoft.Data.SqlClient.Tests.CustomConfigurableRetryLogic, ExternalConfigurableRetryLogic", "getdefaultretry")] public void LoadInvalidCustomRetryLogicType(string typeName, string methodName) { - bool switchValue = true; - RetryLogicConfigs cnnCfg = RetryLogicConfigHelper.CreateRandomConfig(methodName); RetryLogicConfigs cmdCfg = RetryLogicConfigHelper.CreateRandomConfig(methodName); // for sake of reducing the retry time in total @@ -130,10 +102,9 @@ public void LoadInvalidCustomRetryLogicType(string typeName, string methodName) cnnCfg.NumberOfTries = 1; cmdCfg.NumberOfTries = 3; - object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); + object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); Assert.NotNull(loaderObj); - RetryLogicTestHelper.CleanRetryEnabledCache(); s_connectionCRLTest.DefaultOpenWithoutRetry(TcpCnnString, cnnProvider); s_commandCRLTest.NoneRetriableExecuteFail(TcpCnnString, cmdProvider); } @@ -150,12 +121,10 @@ public void InvalidRetryMethodName(string methodName) RetryLogicConfigs cnnCfg = RetryLogicConfigHelper.CreateRandomConfig(methodName); RetryLogicConfigs cmdCfg = RetryLogicConfigHelper.CreateRandomConfig(methodName, @"Don't care!"); - bool switchValue = true; - object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); + object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); Assert.NotNull(loaderObj); // none retriable logic applies. - RetryLogicTestHelper.CleanRetryEnabledCache(); s_connectionCRLTest.DefaultOpenWithoutRetry(TcpCnnString, cnnProvider); s_commandCRLTest.NoneRetriableExecuteFail(TcpCnnString, cmdProvider); } @@ -175,14 +144,12 @@ public void InvalidRetryLogicTypeWithValidInternalMethodName(string typeName) cnnCfg.NumberOfTries = 1; cmdCfg.NumberOfTries = 1; - bool switchValue = true; - object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); + object loaderObj = RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider); Assert.NotNull(loaderObj); - RetryLogicConfigHelper.AssessProvider(cnnProvider, cnnCfg, switchValue); - RetryLogicConfigHelper.AssessProvider(cmdProvider, cmdCfg, switchValue); + RetryLogicConfigHelper.AssessProvider(cnnProvider, cnnCfg); + RetryLogicConfigHelper.AssessProvider(cmdProvider, cmdCfg); // internal type used to resolve the specified method - RetryLogicTestHelper.CleanRetryEnabledCache(); s_connectionCRLTest.ConnectionRetryOpenInvalidCatalogFailed(TcpCnnString, cnnProvider); s_commandCRLTest.RetryExecuteFail(TcpCnnString, cmdProvider); } @@ -195,20 +162,19 @@ public void OutOfRangeTime(TimeSpan deltaTime, TimeSpan minTime, TimeSpan maxTim cnnCfg.DeltaTime = deltaTime; RetryLogicConfigs cmdCfg = RetryLogicConfigHelper.CreateRandomConfig(RetryLogicConfigHelper.RetryMethodName_Fix, @"Don't care!"); - bool switchValue = true; - var ex = Assert.Throws(() => RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider)); + var ex = Assert.Throws(() => RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider)); Assert.Equal(typeof(System.Configuration.ConfigurationErrorsException), ex.InnerException?.GetType()); Assert.Equal(typeof(ArgumentException), ex.InnerException?.InnerException?.GetType()); cnnCfg = RetryLogicConfigHelper.CreateRandomConfig(RetryLogicConfigHelper.RetryMethodName_Fix); cnnCfg.MinTimeInterval = minTime; - ex = Assert.Throws(() => RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider)); + ex = Assert.Throws(() => RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider)); Assert.Equal(typeof(System.Configuration.ConfigurationErrorsException), ex.InnerException?.GetType()); Assert.Equal(typeof(ArgumentException), ex.InnerException?.InnerException?.GetType()); cnnCfg = RetryLogicConfigHelper.CreateRandomConfig(RetryLogicConfigHelper.RetryMethodName_Fix); cnnCfg.MaxTimeInterval = maxTime; - ex = Assert.Throws(() => RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider)); + ex = Assert.Throws(() => RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider)); Assert.Equal(typeof(System.Configuration.ConfigurationErrorsException), ex.InnerException?.GetType()); Assert.Equal(typeof(ArgumentException), ex.InnerException?.InnerException?.GetType()); } @@ -224,8 +190,7 @@ public void InvalidNumberOfTries(int num) cnnCfg.NumberOfTries = num; RetryLogicConfigs cmdCfg = RetryLogicConfigHelper.CreateRandomConfig(RetryLogicConfigHelper.RetryMethodName_Fix, @"Don't care!"); - bool switchValue = true; - var ex = Assert.Throws(() => RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider)); + var ex = Assert.Throws(() => RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider)); Assert.Equal(typeof(System.Configuration.ConfigurationErrorsException), ex.InnerException?.GetType()); Assert.Equal(typeof(ArgumentException), ex.InnerException?.InnerException?.GetType()); } @@ -249,25 +214,12 @@ public void InvalidTransientError(string errors) cnnCfg.TransientErrors = errors; RetryLogicConfigs cmdCfg = RetryLogicConfigHelper.CreateRandomConfig(RetryLogicConfigHelper.RetryMethodName_Fix, @"Don't care!"); - bool switchValue = true; - var ex = Assert.Throws(() => RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, switchValue, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider)); + var ex = Assert.Throws(() => RetryLogicConfigHelper.ReturnLoaderAndProviders(cnnCfg, cmdCfg, out SqlRetryLogicBaseProvider cnnProvider, out SqlRetryLogicBaseProvider cmdProvider)); Assert.Equal(typeof(System.Configuration.ConfigurationErrorsException), ex.InnerException?.GetType()); Assert.Equal(typeof(ArgumentException), ex.InnerException?.InnerException?.GetType()); } #endregion - #region AppContextSwitchManager - [Theory] - [InlineData("Switch.Microsoft.Data.SqlClient.EnableRetryLogic", true)] - [InlineData("Switch.Microsoft.Data.SqlClient.EnableRetryLogic", false)] - public void ContextSwitchMangerTest(string name, bool value) - { - RetryLogicConfigHelper.ApplyContextSwitchByManager(name, value); - AppContext.TryGetSwitch(name, out bool result); - Assert.Equal(value, result); - } - #endregion - #region private methods private void TestConnection(SqlRetryLogicBaseProvider provider, RetryLogicConfigs cnfig) {