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

Automatically adjust the default ConnectRetryCount against OnDemand endpoints #1626

Merged
merged 1 commit into from
May 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -412,9 +412,15 @@ private void CacheConnectionStringProperties()
if (connString != null)
{
_connectRetryCount = connString.ConnectRetryCount;
// For Azure Synapse ondemand connections, set _connectRetryCount to 5 instead of 1 to greatly improve recovery
// success rate. Note: Synapse should be detected first as it could be detected as a regular Azure SQL DB endpoint.
if (_connectRetryCount == 1 && ADP.IsAzureSynapseOnDemandEndpoint(connString.DataSource))
{
_connectRetryCount = 5;
}
// For Azure SQL connection, set _connectRetryCount to 2 instead of 1 will greatly improve recovery
// success rate
if (_connectRetryCount == 1 && ADP.IsAzureSqlServerEndpoint(connString.DataSource))
// success rate
else if (_connectRetryCount == 1 && ADP.IsAzureSqlServerEndpoint(connString.DataSource))
{
_connectRetryCount = 2;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,9 +432,15 @@ private void CacheConnectionStringProperties()
if (connString != null)
{
_connectRetryCount = connString.ConnectRetryCount;
// For Azure Synapse ondemand connections, set _connectRetryCount to 5 instead of 1 to greatly improve recovery
// success rate. Note: Synapse should be detected first as it could be detected as a regular Azure SQL DB endpoint.
if (_connectRetryCount == 1 && ADP.IsAzureSynapseOnDemandEndpoint(connString.DataSource))
{
_connectRetryCount = 5;
}
// For Azure SQL connection, set _connectRetryCount to 2 instead of 1 will greatly improve recovery
// success rate
if (_connectRetryCount == 1 && ADP.IsAzureSqlServerEndpoint(connString.DataSource))
// success rate
else if (_connectRetryCount == 1 && ADP.IsAzureSqlServerEndpoint(connString.DataSource))
{
_connectRetryCount = 2;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -686,13 +686,26 @@ internal static Version GetAssemblyVersion()
}


private const string ONDEMAND_PREFIX = "-ondemand";
private const string AZURE_SYNAPSE = "-ondemand.sql.azuresynapse.";

internal static bool IsAzureSynapseOnDemandEndpoint(string dataSource)
{
return IsEndpoint(dataSource, ONDEMAND_PREFIX) || dataSource.Contains(AZURE_SYNAPSE);
}

internal static readonly string[] s_azureSqlServerEndpoints = { StringsHelper.GetString(Strings.AZURESQL_GenericEndpoint),
StringsHelper.GetString(Strings.AZURESQL_GermanEndpoint),
StringsHelper.GetString(Strings.AZURESQL_UsGovEndpoint),
StringsHelper.GetString(Strings.AZURESQL_ChinaEndpoint)};

// This method assumes dataSource parameter is in TCP connection string format.
internal static bool IsAzureSqlServerEndpoint(string dataSource)
{
return IsEndpoint(dataSource, null);
}

// This method assumes dataSource parameter is in TCP connection string format.
private static bool IsEndpoint(string dataSource, string prefix)
{
int length = dataSource.Length;
// remove server port
Expand All @@ -715,10 +728,10 @@ internal static bool IsAzureSqlServerEndpoint(string dataSource)
length -= 1;
}

// check if servername end with any azure endpoints
// check if servername ends with any endpoints
for (int index = 0; index < s_azureSqlServerEndpoints.Length; index++)
{
string endpoint = s_azureSqlServerEndpoints[index];
string endpoint = string.IsNullOrEmpty(prefix) ? s_azureSqlServerEndpoints[index] : prefix + s_azureSqlServerEndpoints[index];
if (length > endpoint.Length)
{
if (string.Compare(dataSource, length - endpoint.Length, endpoint, 0, endpoint.Length, StringComparison.OrdinalIgnoreCase) == 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Data;
using System.Collections.Generic;
using Xunit;
using System.Reflection;

namespace Microsoft.Data.SqlClient.Tests
{
Expand Down Expand Up @@ -1031,5 +1032,34 @@ public void ConnectionString_IPAddressPreference_Invalid(string value)
Assert.Contains("'ip address preference'", ex.Message, StringComparison.OrdinalIgnoreCase);
Assert.Null(ex.ParamName);
}

[Fact]
public void ConnectionRetryForNonAzureEndpoints()
{
SqlConnection cn = new SqlConnection("Data Source = someserver");
FieldInfo field = typeof(SqlConnection).GetField("_connectRetryCount", BindingFlags.Instance | BindingFlags.NonPublic);
Assert.NotNull(field.GetValue(cn));
Assert.Equal(1, (int)field.GetValue(cn));
}

[Fact]
public void ConnectionRetryForAzureDbEndpoints()
{
SqlConnection cn = new SqlConnection("Data Source = someserver.database.windows.net");
FieldInfo field = typeof(SqlConnection).GetField("_connectRetryCount", BindingFlags.Instance | BindingFlags.NonPublic);
Assert.NotNull(field.GetValue(cn));
Assert.Equal(2, (int)field.GetValue(cn));
}

[Theory]
[InlineData("myserver-ondemand.sql.azuresynapse.net")]
[InlineData("someserver-ondemand.database.windows.net")]
public void ConnectionRetryForAzureOnDemandEndpoints(string serverName)
{
SqlConnection cn = new SqlConnection($"Data Source = {serverName}");
FieldInfo field = typeof(SqlConnection).GetField("_connectRetryCount", BindingFlags.Instance | BindingFlags.NonPublic);
Assert.NotNull(field.GetValue(cn));
Assert.Equal(5, (int)field.GetValue(cn));
}
}
}