Exemple #1
0
 /// <summary>
 /// Create a <see cref="ResilientFuncBuilder{TFunction, TResult}"/> from an existing synchronous function.
 /// </summary>
 /// <param name="function">A synchronous function that is not already resilient.</param>
 /// <returns>A new builder for the operation to configure resiliency.</returns>
 public static ResilientFuncBuilder <Func <TResult>, TResult> AsResilient <TResult>(
     this Func <TResult> function,
     [CallerLineNumber] int sourceLineNumber = 0,
     [CallerFilePath] string sourceFilePath  = "",
     [CallerMemberName] string memberName    = "")
 {
     return(ResilientOperation.From(function, sourceLineNumber, sourceFilePath, memberName));
 }
Exemple #2
0
 /// <summary>
 /// Create a <see cref="ResilientActionBuilder{TAction}"/> from an existing synchronous action.
 /// </summary>
 /// <param name="action">A synchronous action that is not already resilient.</param>
 /// <returns>A new builder for the operation to configure resiliency.</returns>
 public static ResilientActionBuilder <Action> AsResilient(
     this Action action,
     [CallerLineNumber] int sourceLineNumber = 0,
     [CallerFilePath] string sourceFilePath  = "",
     [CallerMemberName] string memberName    = "")
 {
     return(ResilientOperation.From(action, sourceLineNumber, sourceFilePath, memberName));
 }
Exemple #3
0
 /// <summary>
 /// Create a <see cref="ResilientActionBuilder{TAction}"/> from an existing async action with cancellation support.
 /// </summary>
 /// <param name="action">An async action, that supports cancellation, that is not already resilient.</param>
 /// <returns>A new builder for the operation to configure resiliency.</returns>
 public static ResilientActionBuilder <Func <CancellationToken, Task> > AsResilient(
     this Func <CancellationToken, Task> action,
     [CallerLineNumber] int sourceLineNumber = 0,
     [CallerFilePath] string sourceFilePath  = "",
     [CallerMemberName] string memberName    = "")
 {
     return(ResilientOperation.From(action, sourceLineNumber, sourceFilePath, memberName));
 }
        public async Task InvokeAsync(CancellationToken cancellationToken = default)
        {
            // Build wrapped operation
            ActionOperation wrappedOperation = ExecuteAction;

            foreach (var circuitBreakerHandler in CircuitBreakerHandlers)
            {
                wrappedOperation = circuitBreakerHandler(wrappedOperation);
            }

            var totalInfo = new ResilientOperationTotalInfo();

            var partiallyAppliedHandlers = new List <Func <Exception, Task <HandlerResult> > >();

            // Prepare handlers
            foreach (var handler in Handlers)
            {
                var op = new ResilientOperation(ImplicitOperationKey, new ResilientOperationHandlerInfo(), totalInfo, cancellationToken);

                partiallyAppliedHandlers.Add((ex) => handler(op, ex));
            }

            do
            {
                try
                {
                    await wrappedOperation(cancellationToken).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    try
                    {
                        await ProcessHandlers(partiallyAppliedHandlers, ex, cancellationToken);
                    }
                    catch (CircuitBrokenException circuitBrokenEx)
                    {
                        await ProcessHandlers(partiallyAppliedHandlers, circuitBrokenEx, cancellationToken);
                    }
                }
            }while (true);
        }
Exemple #5
0
        public async Task <TResult> InvokeAsync(CancellationToken cancellationToken = default)
        {
            // Build wrapped operation
            Func <CancellationToken, Task <TResult> > wrappedOperation = ExecuteFunc;

            foreach (var circuitBreakerHandler in CircuitBreakerHandlers)
            {
                wrappedOperation = circuitBreakerHandler(wrappedOperation);
            }

            var totalInfo = new ResilientOperationTotalInfo();

            var partiallyAppliedResultHandlers = new List <Func <TResult, Task <ResilientOperation <TResult> > > >();

            // Prepare handlers
            foreach (var handler in ResultHandlers)
            {
                var op = new ResilientOperation <TResult>(ImplicitOperationKey, new ResilientOperationHandlerInfo(), totalInfo, cancellationToken);

                partiallyAppliedResultHandlers.Add(result => handler(op, result));
            }

            var partiallyAppliedHandlers = new List <Func <Exception, Task <ResilientOperation <TResult> > > >();

            // Prepare handlers
            foreach (var handler in Handlers)
            {
                var op = new ResilientOperation <TResult>(ImplicitOperationKey, new ResilientOperationHandlerInfo(), totalInfo, cancellationToken);

                partiallyAppliedHandlers.Add((ex) => handler(op, ex));
            }

            do
            {
                try
                {
                    var result = await wrappedOperation(cancellationToken).ConfigureAwait(false);

                    ResilientOperation <TResult> op = null;

                    foreach (var handler in partiallyAppliedResultHandlers)
                    {
                        op = await handler(result).ConfigureAwait(false);

                        if (op.HandlerResult == HandlerResult.Unhandled)
                        {
                            continue;
                        }
                        else if (op.HandlerResult == HandlerResult.Retry)
                        {
                            break;
                        }
                        else if (op.HandlerResult == HandlerResult.Break)
                        {
                            return(result);
                        }
                        else if (op.HandlerResult == HandlerResult.Return)
                        {
                            return(op.Result);
                        }
                    }

                    if (op?.HandlerResult == HandlerResult.Retry)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        continue;
                    }

                    return(result);
                }
                catch (Exception ex) when(!(ex is OperationCanceledException))
                {
                    var exToHandle = ex;

                    ResilientOperation <TResult> op = null;

                    do
                    {
                        try
                        {
                            foreach (var handler in partiallyAppliedHandlers)
                            {
                                op = await handler(exToHandle).ConfigureAwait(false);

                                if (op.HandlerResult == HandlerResult.Unhandled)
                                {
                                    continue;
                                }
                                else if (op.HandlerResult == HandlerResult.Retry)
                                {
                                    break;
                                }
                                else if (op.HandlerResult == HandlerResult.Break)
                                {
                                    break;
                                }
                                else if (op.HandlerResult == HandlerResult.Return)
                                {
                                    return(op.Result);
                                }
                            }

                            if (op?.HandlerResult == HandlerResult.Retry)
                            {
                                break;
                            }

                            ExceptionDispatchInfo.Capture(exToHandle).Throw();
                        }
                        catch (Exception handlerEx) when(handlerEx != exToHandle && !(handlerEx is OperationCanceledException))
                        {
                            exToHandle = handlerEx;

                            continue;
                        }
                    }while (true);

                    continue;
                }
            }while (true);
        }
 public static Task WaitAsync(this ResilientOperation op, TimeSpan period) =>
 ResilientOperation.WaiterFactory(op.CancellationToken).WaitAsync(period);
        public static async Task WaitThenRetryAsync(this ResilientOperation op, TimeSpan period)
        {
            await op.WaitAsync(period).ConfigureAwait(false);

            op.Retry();
        }