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

Remove Configurable Retry Logic safety switch #1254

Merged
merged 2 commits into from
Sep 17, 2021
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
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 IsRetriable => SqlConfigurableRetryFactory.IsRetriable(RetryLogicProvider);
cheenamalhotra marked this conversation as resolved.
Show resolved Hide resolved

/// <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 = IsRetriable ?
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 (IsRetriable)
{
InternalExecuteNonQueryWithRetry(sendToPipe: false, timeout: CommandTimeout, out _, asyncWrite: false, inRetry: false);
}
Expand Down Expand Up @@ -1706,7 +1706,7 @@ public XmlReader ExecuteXmlReader()
WriteBeginExecuteEvent();
// use the reader to consume metadata
SqlDataReader ds;
ds = IsRetryEnabled ?
ds = IsRetriable ?
RunExecuteReaderWithRetry(CommandBehavior.SequentialAccess, RunBehavior.ReturnImmediately, returnStream: true) :
RunExecuteReader(CommandBehavior.SequentialAccess, RunBehavior.ReturnImmediately, returnStream: true);
success = true;
Expand Down Expand Up @@ -2043,7 +2043,7 @@ protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
{
WriteBeginExecuteEvent();
statistics = SqlStatistics.StartTimer(Statistics);
return IsRetryEnabled ?
return IsRetriable ?
RunExecuteReaderWithRetry(behavior, RunBehavior.ReturnImmediately, returnStream: true) :
RunExecuteReader(behavior, RunBehavior.ReturnImmediately, returnStream: true);
}
Expand Down Expand Up @@ -2548,7 +2548,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 ?
=> IsRetriable ?
InternalExecuteNonQueryWithRetryAsync(cancellationToken) :
InternalExecuteNonQueryAsync(cancellationToken);

Expand Down Expand Up @@ -2648,7 +2648,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 ?
=> IsRetriable ?
InternalExecuteReaderWithRetryAsync(behavior, cancellationToken) :
InternalExecuteReaderAsync(behavior, cancellationToken);

Expand Down Expand Up @@ -2821,7 +2821,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 ?
=> IsRetriable ?
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 IsRetriable => 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 (!(IsRetriable ? 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 ?
=> IsRetriable ?
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 IsRetriable => 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 = IsRetriable ?
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 (IsRetriable)
{
InternalExecuteNonQueryWithRetry(ADP.ExecuteNonQuery, sendToPipe: false, CommandTimeout, out usedCache, asyncWrite: false, inRetry: false);
}
Expand Down Expand Up @@ -2098,7 +2098,7 @@ public XmlReader ExecuteXmlReader()

// use the reader to consume metadata
SqlDataReader ds;
ds = IsRetryEnabled ?
ds = IsRetriable ?
RunExecuteReaderWithRetry(CommandBehavior.SequentialAccess, RunBehavior.ReturnImmediately, true, ADP.ExecuteXmlReader) :
RunExecuteReader(CommandBehavior.SequentialAccess, RunBehavior.ReturnImmediately, true, ADP.ExecuteXmlReader);
XmlReader result = CompleteXmlReader(ds);
Expand Down Expand Up @@ -2426,7 +2426,7 @@ private SqlDataReader ExecuteReaderWithRetry(CommandBehavior behavior, string me
try
{
statistics = SqlStatistics.StartTimer(Statistics);
return IsRetryEnabled ?
return IsRetriable ?
ExecuteReaderWithRetry(CommandBehavior.Default, ADP.ExecuteReader) :
ExecuteReader(CommandBehavior.Default, ADP.ExecuteReader);
}
Expand All @@ -2444,7 +2444,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 IsRetriable ?
ExecuteReaderWithRetry(behavior, ADP.ExecuteReader) :
ExecuteReader(behavior, ADP.ExecuteReader);
}
Expand Down Expand Up @@ -2960,7 +2960,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 ?
=> IsRetriable ?
InternalExecuteNonQueryWithRetryAsync(cancellationToken) :
InternalExecuteNonQueryAsync(cancellationToken);

Expand Down Expand Up @@ -3039,25 +3039,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 ?
=> IsRetriable ?
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 ?
=> IsRetriable ?
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 ?
=> IsRetriable ?
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 ?
=> IsRetriable ?
InternalExecuteReaderWithRetryAsync(behavior, cancellationToken) :
InternalExecuteReaderAsync(behavior, cancellationToken);

Expand Down Expand Up @@ -3203,7 +3203,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 ?
=> IsRetriable ?
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 IsRetriable => 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 (!(IsRetriable ? 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 ?
=> IsRetriable ?
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