// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // using System.Collections.Generic; using System.Data.SqlClient; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { internal abstract partial class RetryPolicy { /// /// Provides the error detection logic for temporary faults that are commonly found in SQL Azure. /// This strategy is similar to SqlAzureTemporaryErrorDetectionStrategy, but it exposes ways /// to accept a certain exception and treat it as passing. /// For example, if we are retrying, and we get a failure that an object already exists, we might /// want to consider this as passing since the first execution that has timed out (or failed for some other temporary error) /// might have managed to create the object. /// internal class SqlAzureTemporaryAndIgnorableErrorDetectionStrategy : ErrorDetectionStrategyBase, IErrorDetectionStrategy { /// /// Azure error that can be ignored /// private readonly IList ignorableAzureErrors = null; public SqlAzureTemporaryAndIgnorableErrorDetectionStrategy(params int[] ignorableErrors) { this.ignorableAzureErrors = ignorableErrors; } protected override bool CanRetrySqlException(SqlException sqlException) { // Enumerate through all errors found in the exception. bool foundRetryableError = false; foreach (SqlError err in sqlException.Errors) { RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err); if (!RetryPolicyUtils.IsRetryableAzureError(err.Number)) { return false; } foundRetryableError = true; } return foundRetryableError; } protected override bool ShouldIgnoreSqlException(SqlException sqlException) { int errorNumber = sqlException.Number; if (ignorableAzureErrors == null) { return false; } return ignorableAzureErrors.Contains(errorNumber); } } } }