From c307a0f7f2af8d0037680ac3a4f071ed6ddc570a Mon Sep 17 00:00:00 2001 From: Adam McCoy Date: Thu, 2 Feb 2023 16:41:50 +1100 Subject: [PATCH] Retry pooled connection timeout (#243) * Refactor a bit * Retry pooled connection failures --- ...DatabaseTransientErrorDetectionStrategy.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/source/Nevermore/Transient/SqlDatabaseTransientErrorDetectionStrategy.cs b/source/Nevermore/Transient/SqlDatabaseTransientErrorDetectionStrategy.cs index 1d06e371..c8ce5389 100644 --- a/source/Nevermore/Transient/SqlDatabaseTransientErrorDetectionStrategy.cs +++ b/source/Nevermore/Transient/SqlDatabaseTransientErrorDetectionStrategy.cs @@ -198,18 +198,27 @@ sealed class SqlDatabaseTransientErrorDetectionStrategy : ITransientErrorDetecti public bool IsTransient(Exception ex) { - if (ex is TimeoutException) return true; + return ex switch + { + TimeoutException => true, + InvalidOperationException invalidOperationException => IsPooledConnectTimeout(invalidOperationException), + SqlException sqlException => IsTransientSqlException(sqlException), + _ => false + }; + } - var sqlException = ex as SqlException; - if (sqlException == null) return false; + static bool IsPooledConnectTimeout(InvalidOperationException exception) + => exception.Message.Contains("The timeout period elapsed prior to obtaining a connection from the pool."); + static bool IsTransientSqlException(SqlException exception) + { // If this error was caused by throttling on the server we can augment the exception with more detail // I don't feel awesome about mutating the exception directly but it seems the most pragmatic way to add value - var sqlErrors = sqlException.Errors.OfType().ToArray(); + var sqlErrors = exception.Errors.OfType().ToArray(); var firstThrottlingError = sqlErrors.FirstOrDefault(x => x.Number == ThrottlingCondition.ThrottlingErrorNumber); if (firstThrottlingError != null) { - AugmentSqlExceptionWithThrottlingDetails(firstThrottlingError, sqlException); + AugmentSqlExceptionWithThrottlingDetails(firstThrottlingError, exception); return true; }