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);
        }
示例#2
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);
        }