Skip to content

Commit

Permalink
Remove Configurable Retry Logic safety switch (#1254)
Browse files Browse the repository at this point in the history
  • Loading branch information
DavoudEshtehari authored Sep 17, 2021
1 parent 576fadb commit 831287f
Show file tree
Hide file tree
Showing 11 changed files with 50 additions and 162 deletions.
6 changes: 0 additions & 6 deletions BUILDGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ private SqlInternalConnectionTds InternalTdsConnection
}
}

private static bool IsRetryEnabled => LocalAppContextSwitches.IsRetryEnabled;
private bool IsProviderRetriable => SqlConfigurableRetryFactory.IsRetriable(RetryLogicProvider);

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/RetryLogicProvider/*' />
[Browsable(false)]
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -1700,7 +1700,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;
Expand Down Expand Up @@ -2033,7 +2033,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);
}
Expand Down Expand Up @@ -2535,7 +2535,7 @@ private SqlDataReader InternalEndExecuteReader(IAsyncResult asyncResult, bool is

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteNonQueryAsync[@name="CancellationToken"]/*'/>
public override Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalExecuteNonQueryWithRetryAsync(cancellationToken) :
InternalExecuteNonQueryAsync(cancellationToken);

Expand Down Expand Up @@ -2635,7 +2635,7 @@ protected override Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior b

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteReaderAsync[@name="commandBehaviorAndCancellationToken"]/*'/>
new public Task<SqlDataReader> ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalExecuteReaderWithRetryAsync(behavior, cancellationToken) :
InternalExecuteReaderAsync(behavior, cancellationToken);

Expand Down Expand Up @@ -2808,7 +2808,7 @@ public Task<XmlReader> ExecuteXmlReaderAsync()

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteXmlReaderAsync[@name="CancellationToken"]/*'/>
public Task<XmlReader> ExecuteXmlReaderAsync(CancellationToken cancellationToken)
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalExecuteXmlReaderWithRetryAsync(cancellationToken) :
InternalExecuteXmlReaderAsync(cancellationToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private static readonly ConcurrentDictionary<string, IList<string>> _ColumnEncry
private static readonly Action<object> s_openAsyncCancel = OpenAsyncCancel;
private static readonly Action<Task<object>, object> s_openAsyncComplete = OpenAsyncComplete;

private static bool IsRetryEnabled => LocalAppContextSwitches.IsRetryEnabled;
private bool IsProviderRetriable => SqlConfigurableRetryFactory.IsRetriable(RetryLogicProvider);

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/RetryLogicProvider/*' />
[Browsable(false)]
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -1575,7 +1575,7 @@ private Task InternalOpenWithRetryAsync(CancellationToken cancellationToken)

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/OpenAsync/*' />
public override Task OpenAsync(CancellationToken cancellationToken)
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalOpenWithRetryAsync(cancellationToken) :
InternalOpenAsync(cancellationToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,7 @@ private bool IsShiloh
}
}

private static bool IsRetryEnabled => LocalAppContextSwitches.IsRetryEnabled;
private bool IsProviderRetriable => SqlConfigurableRetryFactory.IsRetriable(RetryLogicProvider);

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/RetryLogicProvider/*' />
[
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -2092,7 +2092,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);
Expand Down Expand Up @@ -2415,7 +2415,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);
}
Expand All @@ -2433,7 +2433,7 @@ private SqlDataReader ExecuteReaderWithRetry(CommandBehavior behavior, string me
{
SqlClientEventSource.Log.TryCorrelationTraceEvent("<sc.SqlCommand.ExecuteReader|API|Correlation> ObjectID {0}, behavior={1}, ActivityID {2}", ObjectID, (int)behavior, ActivityCorrelator.Current);

return IsRetryEnabled ?
return IsProviderRetriable ?
ExecuteReaderWithRetry(behavior, ADP.ExecuteReader) :
ExecuteReader(behavior, ADP.ExecuteReader);
}
Expand Down Expand Up @@ -2945,7 +2945,7 @@ private Task<int> InternalExecuteNonQueryWithRetryAsync(CancellationToken cancel

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteNonQueryAsync[@name="CancellationToken"]/*'/>
public override Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalExecuteNonQueryWithRetryAsync(cancellationToken) :
InternalExecuteNonQueryAsync(cancellationToken);

Expand Down Expand Up @@ -3024,25 +3024,25 @@ private Task<SqlDataReader> InternalExecuteReaderWithRetryAsync(CommandBehavior

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteReaderAsync[@name="default"]/*'/>
new public Task<SqlDataReader> ExecuteReaderAsync()
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalExecuteReaderWithRetryAsync(CommandBehavior.Default, CancellationToken.None) :
InternalExecuteReaderAsync(CommandBehavior.Default, CancellationToken.None);

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteReaderAsync[@name="CommandBehavior"]/*'/>
new public Task<SqlDataReader> ExecuteReaderAsync(CommandBehavior behavior)
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalExecuteReaderWithRetryAsync(behavior, CancellationToken.None) :
InternalExecuteReaderAsync(behavior, CancellationToken.None);

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteReaderAsync[@name="CancellationToken"]/*'/>
new public Task<SqlDataReader> ExecuteReaderAsync(CancellationToken cancellationToken)
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalExecuteReaderWithRetryAsync(CommandBehavior.Default, cancellationToken) :
InternalExecuteReaderAsync(CommandBehavior.Default, cancellationToken);

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteReaderAsync[@name="commandBehaviorAndCancellationToken"]/*'/>
new public Task<SqlDataReader> ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalExecuteReaderWithRetryAsync(behavior, cancellationToken) :
InternalExecuteReaderAsync(behavior, cancellationToken);

Expand Down Expand Up @@ -3188,7 +3188,7 @@ private Task<XmlReader> InternalExecuteXmlReaderWithRetryAsync(CancellationToken

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteXmlReaderAsync[@name="CancellationToken"]/*'/>
public Task<XmlReader> ExecuteXmlReaderAsync(CancellationToken cancellationToken)
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalExecuteXmlReaderWithRetryAsync(cancellationToken) :
InternalExecuteXmlReaderAsync(cancellationToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ internal List<string> GetColumnEncryptionCustomKeyStoreProvidersNames()

// Retry Logic
private SqlRetryLogicBaseProvider _retryLogicProvider;
private static bool IsRetryEnabled => LocalAppContextSwitches.IsRetryEnabled;
private bool IsProviderRetriable => SqlConfigurableRetryFactory.IsRetriable(RetryLogicProvider);

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnection.xml' path='docs/members[@name="SqlConnection"]/RetryLogicProvider/*' />
[
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -1882,7 +1882,7 @@ private Task InternalOpenWithRetryAsync(CancellationToken cancellationToken)

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlConnection.xml' path='docs/members[@name="SqlConnection"]/OpenAsync/*' />
public override Task OpenAsync(CancellationToken cancellationToken)
=> IsRetryEnabled ?
=> IsProviderRetriable ?
InternalOpenWithRetryAsync(cancellationToken) :
InternalOpenAsync(cancellationToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ public static SqlRetryLogicBaseProvider CreateNoneRetryProvider()
return new SqlRetryLogicProvider(retryLogic);
}

/// <summary>
/// Verifies the provider which is not null and doesn't include SqlNoneIntervalEnumerator enumerator object.
/// </summary>
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<int> retriableConditions)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,8 @@ public static SqlRetryLogicBaseProvider GetConnectionProvider(object loader)
public static SqlRetryLogicBaseProvider GetCommandProvider(object loader)
=> GetValue<SqlRetryLogicBaseProvider>(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)
{
Expand Down Expand Up @@ -142,9 +137,8 @@ public static IEnumerable<object[]> 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);
Expand Down
Loading

0 comments on commit 831287f

Please sign in to comment.