From 00ad16e79644efdfd2ffce5c7f979a7cd5fd5181 Mon Sep 17 00:00:00 2001 From: Alex Ma Date: Tue, 6 Sep 2022 13:42:43 -0700 Subject: [PATCH] Alex/fixforretrysleeping (#1669) * added getResponseConnect function * added WIP changes to getResponseConnect * changed retry number to be smaller number * added comments and changed max tries * added changes * added more changes * added notification class * made changes to fix * added null fix --- .../Connection/ConnectionService.cs | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs index dd0897cb..80cf7c71 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs @@ -35,6 +35,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection private const string SqlAzureEdition = "SQL Azure"; public const int MaxTolerance = 2 * 60; // two minutes - standard tolerance across ADS for AAD tokens + public const int MaxServerlessReconnectTries = 5; // Max number of tries to wait for a serverless database to start up when its paused before giving up. + /// /// Singleton service instance /// @@ -377,7 +379,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection } // Try to open a connection with the given ConnectParams - ConnectionCompleteParams response = await TryOpenConnection(connectionInfo, connectionParams); + ConnectionCompleteParams? response = await this.TryOpenConnectionWithRetry(connectionInfo, connectionParams); if (response != null) { return response; @@ -400,6 +402,33 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection return completeParams; } + private async Task TryOpenConnectionWithRetry(ConnectionInfo connectionInfo, ConnectParams connectionParams) + { + int counter = 0; + ConnectionCompleteParams? response = null; + while (counter <= MaxServerlessReconnectTries) + { + // The OpenAsync function used in TryOpenConnection does not retry when a database is sleeping. + // SqlClient will be implemented at a later time, which will have automatic retries. + response = await TryOpenConnection(connectionInfo, connectionParams); + // If a serverless database is sleeping, it will return this error number and will need to be retried. + // See here for details: https://docs.microsoft.com/en-us/azure/azure-sql/database/serverless-tier-overview?view=azuresql#connectivity + if (response?.ErrorNumber == 40613) + { + counter++; + if(counter != MaxServerlessReconnectTries) { + Logger.Information($"Database for connection {connectionInfo.OwnerUri} is paused, retrying connection. Attempt #{counter}"); + } + } + else + { + // Every other response, we can stop. + break; + } + } + return response; + } + private void TryCloseConnectionTemporaryConnection(ConnectParams connectionParams, ConnectionInfo connectionInfo) { try