Polly's Fallback中的动态代表

问题描述 投票:0回答:1

我在PolicyRegistry中有以下策略可以在全局重用:

var fallbackPolicy = Policy
        .Handle<DrmException>().OrInner<DrmException>()
        .Fallback(
            fallbackAction: () => { //should commit or dispose the transaction here using a passed in Func or Action },
            onFallback: (exception) => { Log.Error().Exception(exception).Message($"Exception occurred, message: {exception.Message}.").Write(); }
        );

我有以下代码,我想实现fallbackPolicy

   if(Settings.DRM_ENABLED)
       drmManager.ExecuteAsync(new DeleteUser(123).Wait();//HTTP Call, throws DrmException if unsuccessful

       //in some cases, there is an if(transaction == null) here (if transaction was passed as a parameter and needs to be committed here)
       transaction.Commit();//if not thrown - commits the transaction

我希望它看起来像这样:

var fallbackPolicy = Policy
            .Handle<DrmException>().OrInner<DrmException>()
            .Fallback(
                fallbackAction: (transaction) => { transaction.Dispose(); },
                onFallback: (exception) => { Log.Error().Exception(exception).Message($"Exception occurred, message: {exception.Message}.").Write(); }
            );    

fallbackPolicy.Execute(() => drmManager.ExecuteAsync(new DeleteUser(123).Wait(), transaction)

据我所知,fallbackPolicy.Execute执行Action / Func要么成功,在这种情况下fallbackPolicy没有被击中或失败,在这种情况下fallbackPolicy踢了一些预定义的fallbackAction

我想要做的是在执行策略时传入两个处理程序(onFail(transaction)处理事务和onSuccess(transaction)提交事务)。有没有更简单的方法来做它而不是包装它或使用Polly的上下文?

.net fallback transient polly
1个回答
2
投票

感觉像这里有几个单独的问题:

  1. 如何使集中定义的FallbackPolicy做一些动态的事情?
  2. 如何让一个FallbackPolicy做两件事?
  3. 在Polly的混合体中,我如何才能在整体失败方面做到一件事,在整体失败方面做到另一件事?

我将分别回答这些问题,为您提供一个完整的工具包来构建您自己的解决方案 - 以及未来的读者 - 但您可能不需要这三个来实现您的目标。如果您只想要一个解决方案,请减少到3.

1.如何使集中定义的FallbackPolicy做一些动态的事情?

对于任何集中定义的策略,yes Context是您可以传递特定于该执行的内容的方式。参考文献:discussion in a Polly issue; blog post

你的q的一部分似乎围绕使FallbackPolicy两个日志;并处理交易。所以......

2.如何让一个FallbackPolicy做两件事?

你可以传递一些动态的东西(每个上面)。另一种选择是使用两种不同的回退策略。你可以use the same kind of policy multiple times in a PolicyWrap。因此,您可以定义一个集中存储的FallbackPolicy来执行日志记录,并保持简单,非动态:

var loggingFallbackPolicy = Policy
    .Handle<DrmException>().OrInner<DrmException>()
    .Fallback(fallbackAction: () => { /* maybe nothing, maybe rethrow - see discussion below */ },
         onFallback: (exception) => { /* logging; */ });

然后,您可以在本地定义另一个FallbackPolicy以在失败时回滚事务。由于它是在本地定义的,你可以使用闭包将transaction变量传递给它的fallbackAction:(在这种情况下你不必使用Context)。

注意:如果在FallbackPolicy中使用两个PolicyWraps,则需要使内部FallbackPolicy重新抛出(而不是吞咽)处理的异常,以便外部FallbackPolicy也处理它。


Re:

我想做的是传入两个处理程序(onFail(transaction)处理事务和onSuccess(transaction)提交事务)

没有任何政策可以提供成功的特殊处理,但是:

3.在Polly的混合体中,我如何才能在整体失败中做到一件事,在另一件事上取得全面成功?

使用.ExecuteAndCapture(...)。这将返回一个PolicyResult,其属性为.Outcome == OutcomeType.SuccessfulOutcomeType.Failure(以及其他信息:请参阅documentation

整体而言,类似于:

var logAndRethrowFallbackPolicy = Policy
    .Handle<DrmException>().OrInner<DrmException>()
    .Fallback(fallbackAction: (exception, context, token) => { 
        throw exception; // intentional rethrow so that the 'capture' of ExecuteAndCapture reacts.  Use ExceptionDispatchInfo if you care about the original call stack.
        },
        onFallback: (exception, context) => { /* logging */ });

在执行现场:

PolicyResult result = myPolicies.ExecuteAndCapture(() => ... ); // where myPolicies is some PolicyWrap with logAndRethrowFallbackPolicy outermost
if (result.Outcome == OutcomeType.Successful)
    { transaction.Commit(); }
else
    { transaction.Dispose(); }
© www.soinside.com 2019 - 2024. All rights reserved.