// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // using System; using System.Data.SqlClient; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { public abstract partial class RetryPolicy { public interface IErrorDetectionStrategy { /// /// Determines whether the specified exception represents a temporary failure that can be compensated by a retry. /// /// The exception object to be verified. /// True if the specified exception is considered as temporary, otherwise false. bool CanRetry(Exception ex); /// /// Determines whether the specified exception can be ignored. /// /// The exception object to be verified. /// True if the specified exception is considered as non-harmful. bool ShouldIgnoreError(Exception ex); } /// /// Base class with common retry logic. The core behavior for retrying non SqlExceptions is the same /// across retry policies /// public abstract class ErrorDetectionStrategyBase : IErrorDetectionStrategy { public bool CanRetry(Exception ex) { if (ex != null) { SqlException sqlException; if ((sqlException = ex as SqlException) != null) { return CanRetrySqlException(sqlException); } if (ex is InvalidOperationException) { // Operations can throw this exception if the connection is killed before the write starts to the server // However if there's an inner SqlException it may be a CLR load failure or other non-transient error if (ex.InnerException != null && ex.InnerException is SqlException) { return CanRetry(ex.InnerException); } return true; } if (ex is TimeoutException) { return true; } } return false; } public bool ShouldIgnoreError(Exception ex) { if (ex != null) { SqlException sqlException; if ((sqlException = ex as SqlException) != null) { return ShouldIgnoreSqlException(sqlException); } if (ex is InvalidOperationException) { // Operations can throw this exception if the connection is killed before the write starts to the server // However if there's an inner SqlException it may be a CLR load failure or other non-transient error if (ex.InnerException != null && ex.InnerException is SqlException) { return ShouldIgnoreError(ex.InnerException); } } } return false; } protected virtual bool ShouldIgnoreSqlException(SqlException sqlException) { return false; } protected abstract bool CanRetrySqlException(SqlException sqlException); } } }