Esempio n. 1
0
    /// <summary>
    /// Processes an action with this retry policy.
    /// </summary>
    /// <param name="policy">The retry policy.</param>
    /// <param name="action">The async action which will return a result to process.</param>
    /// <param name="needThrow">A handler to check if need throw the exception without retry.</param>
    /// <param name="cancellationToken">The optional cancellation token.</param>
    /// <returns>The processing retry result.</returns>
    public static async Task <RetryResult <T> > ProcessAsync <T>(this IRetryPolicy policy, Func <CancellationToken, Task <T> > action, Func <Exception, Exception> needThrow, CancellationToken cancellationToken = default)
    {
        var result = new RetryResult <T>();

        if (action == null)
        {
            return(result);
        }
        if (needThrow == null)
        {
            needThrow = ex => ex;
        }
        var retry = policy?.CreateInstance() ?? new InternalRetryInstance();

        while (true)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();
                var r = await action(cancellationToken);

                result.Success(r);
                return(result);
            }
            catch (Exception ex)
            {
                result.Fail(ex);
                ex = needThrow(ex);
                if (ex != null)
                {
                    throw ex;
                }
            }

            var span = retry.Next();
            if (!span.HasValue)
            {
                result.End();
                return(result);
            }

            await Task.Delay(span.Value, cancellationToken);
        }
    }
Esempio n. 2
0
    /// <summary>
    /// Enables retry policy to process.
    /// </summary>
    /// <param name="cancellationToken">The optional cancellation token.</param>
    /// <returns>The processing retry result.</returns>
    public async Task <RetryResult> ProcessAsync(CancellationToken cancellationToken = default)
    {
        State = TaskStates.Initializing;
        var result = new RetryResult();
        var retry  = RetryPolicy?.CreateInstance() ?? new InternalRetryInstance();

        State = TaskStates.Working;
        while (true)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();
            }
            catch (OperationCanceledException)
            {
                State = TaskStates.Canceled;
                throw;
            }
            catch (ObjectDisposedException)
            {
                State = TaskStates.Canceled;
                throw;
            }

            try
            {
                await OnProcessAsync(cancellationToken);

                Processing?.Invoke(this, new RetryEventArgs(retry.ProcessTime));
                State = TaskStates.Done;
                result.Success();
                return(result);
            }
            catch (Exception ex)
            {
                State = TaskStates.WaitingToRetry;
                result.Fail(ex);
                try
                {
                    ex = ExceptionHandler.GetException(ex);
                }
                catch (Exception)
                {
                    State = TaskStates.Faulted;
                    throw;
                }

                if (ex != null)
                {
                    State = TaskStates.Faulted;
                    throw ex;
                }
            }

            var span = retry.Next();
            if (!span.HasValue)
            {
                State = TaskStates.Faulted;
                result.End();
                return(result);
            }

            await Task.Delay(span.Value, cancellationToken);

            State = TaskStates.Retrying;
        }
    }