//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// This code is copied from the source described in the comment below.
// =======================================================================================
// Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series
//
// This sample is supplemental to the technical guidance published on the community
// blog at http://blogs.msdn.com/appfabriccat/ and copied from
// sqlmain ./sql/manageability/mfx/common/
//
// =======================================================================================
// Copyright © 2012 Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
// EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT.
// =======================================================================================
// namespace Microsoft.SQL.CAT.BestPractices.SqlAzure.Framework
// namespace Microsoft.SqlServer.Management.Common
using System;
using Microsoft.Data.SqlClient;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Threading;
using Microsoft.SqlTools.Hosting.Utility;
namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection
{
///
/// Implements a policy defining and implementing the retry mechanism for unreliable actions.
///
internal abstract partial class RetryPolicy
{
///
/// Defines a callback delegate which will be invoked whenever a retry condition is encountered.
///
/// The state of current retry attempt.
internal delegate void RetryCallbackDelegate(RetryState retryState);
///
/// Defines a callback delegate which will be invoked whenever an error is ignored on retry.
///
/// The state of current retry attempt.
internal delegate void IgnoreErrorCallbackDelegate(RetryState retryState);
private readonly IErrorDetectionStrategy _errorDetectionStrategy;
protected RetryPolicy(IErrorDetectionStrategy strategy)
{
Contract.Assert(strategy != null);
_errorDetectionStrategy = strategy;
this.FastFirstRetry = true;
//TODO Defect 1078447 Validate whether CommandTimeout needs to be used differently in schema/data scenarios
this.CommandTimeoutInSeconds = AmbientSettings.LongRunningQueryTimeoutSeconds;
}
///
/// An instance of a callback delegate which will be invoked whenever a retry condition is encountered.
///
public event RetryCallbackDelegate RetryOccurred;
///
/// An instance of a callback delegate which will be invoked whenever an error is ignored on retry.
///
public event IgnoreErrorCallbackDelegate IgnoreErrorOccurred;
///
/// Gets or sets a value indicating whether or not the very first retry attempt will be made immediately
/// whereas the subsequent retries will remain subject to retry interval.
///
public bool FastFirstRetry { get; set; }
///
/// Gets or sets the timeout in seconds of sql commands
///
public int CommandTimeoutInSeconds
{
get;
set;
}
///
/// Gets the error detection strategy of this retry policy
///
internal IErrorDetectionStrategy ErrorDetectionStrategy
{
get
{
return _errorDetectionStrategy;
}
}
///
/// We should only ignore errors if they happen after the first retry.
/// This flag is used to allow the ignore even on first try, for testing purposes.
///
///
/// This flag is currently being used for TESTING PURPOSES ONLY.
///
internal bool ShouldIgnoreOnFirstTry
{
get;
set;
}
protected static bool IsLessThanMaxRetryCount(int currentRetryCount, int maxRetryCount)
{
return currentRetryCount <= maxRetryCount;
}
///
/// Repetitively executes the specified action while it satisfies the current retry policy.
///
/// A delegate representing the executable action which doesn't return any results.
/// Cancellation token to cancel action between retries.
public void ExecuteAction(Action action, CancellationToken? token = null)
{
ExecuteAction(
_ => action(), token);
}
///
/// Repetitively executes the specified action while it satisfies the current retry policy.
///
/// A delegate representing the executable action which doesn't return any results.
/// Cancellation token to cancel action between retries.
public void ExecuteAction(Action action, CancellationToken? token = null)
{
ExecuteAction