Polly 后备中的动态委托
Dynamic delegates in Polly’s Fallback
我在 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 的上下文?
感觉这里有几个单独的问题:
- 如何让 centrally-defined FallbackPolicy 做一些动态的事情?
- 如何让一个 FallbackPolicy 做两件事?
- 有了 Polly,我怎样才能在整体失败时做一件事而在整体成功时做另一件事?
我将分别回答这些问题,以便为您提供一个完整的工具包来构建您自己的解决方案 - 并为未来的读者提供 - 但您可能不需要全部三个来实现您的目标。如果你只是想要一个解决方案,请切换到 3。。
1.我怎样才能让 centrally-defined FallbackPolicy 做一些动态的事情?
对于集中定义的任何策略,是的 Context
是您可以为该执行传递特定内容的方式。参考资料:discussion in a Polly issue; blog post.
你的部分问题似乎是让 FallbackPolicy
都记录下来;并处理交易。所以...
2。如何让一个 FallbackPolicy 做两件事?
您可以传递一些动态的东西(如上)。另一种选择是使用两种不同的回退策略。你可以use the same kind of policy multiple times in a PolicyWrap。所以你可以定义一个 centrally-stored FallbackPolicy
来只做日志记录,并保持简单,non-dynamic:
var loggingFallbackPolicy = Policy
.Handle<DrmException>().OrInner<DrmException>()
.Fallback(fallbackAction: () => { /* maybe nothing, maybe rethrow - see discussion below */ },
onFallback: (exception) => { /* logging; */ });
然后您可以在本地定义另一个 FallbackPolicy
以在失败时回滚事务。由于它是在本地定义的,因此您可以使用闭包将 transaction
变量传递给它的 fallbackAction:
(在这种情况下,您不必使用 Context
)。
注意:如果在一个PolicyWrap
中使用两个FallbackPolicy
,你需要将内部的FallbackPolicy
设为[=64] =]重新抛出(不是吞下)已处理的异常,以便外部FallbackPolicy
也处理它。
回复:
What I would like to do is to pass in two handlers (onFail(transaction)
which
disposes the transaction and onSuccess(transaction)
which commits the transaction)
没有任何政策对成功提供特殊处理,但是:
3。有了 Polly,我怎样才能在整体失败时做一件事而在整体成功时做另一件事?
使用.ExecuteAndCapture(...)
. This returns a PolicyResult
with property .Outcome == OutcomeType.Successful
or OutcomeType.Failure
(and other info: see 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(); }
我在 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 的上下文?
感觉这里有几个单独的问题:
- 如何让 centrally-defined FallbackPolicy 做一些动态的事情?
- 如何让一个 FallbackPolicy 做两件事?
- 有了 Polly,我怎样才能在整体失败时做一件事而在整体成功时做另一件事?
我将分别回答这些问题,以便为您提供一个完整的工具包来构建您自己的解决方案 - 并为未来的读者提供 - 但您可能不需要全部三个来实现您的目标。如果你只是想要一个解决方案,请切换到 3。。
1.我怎样才能让 centrally-defined FallbackPolicy 做一些动态的事情?
对于集中定义的任何策略,是的 Context
是您可以为该执行传递特定内容的方式。参考资料:discussion in a Polly issue; blog post.
你的部分问题似乎是让 FallbackPolicy
都记录下来;并处理交易。所以...
2。如何让一个 FallbackPolicy 做两件事?
您可以传递一些动态的东西(如上)。另一种选择是使用两种不同的回退策略。你可以use the same kind of policy multiple times in a PolicyWrap。所以你可以定义一个 centrally-stored FallbackPolicy
来只做日志记录,并保持简单,non-dynamic:
var loggingFallbackPolicy = Policy
.Handle<DrmException>().OrInner<DrmException>()
.Fallback(fallbackAction: () => { /* maybe nothing, maybe rethrow - see discussion below */ },
onFallback: (exception) => { /* logging; */ });
然后您可以在本地定义另一个 FallbackPolicy
以在失败时回滚事务。由于它是在本地定义的,因此您可以使用闭包将 transaction
变量传递给它的 fallbackAction:
(在这种情况下,您不必使用 Context
)。
注意:如果在一个PolicyWrap
中使用两个FallbackPolicy
,你需要将内部的FallbackPolicy
设为[=64] =]重新抛出(不是吞下)已处理的异常,以便外部FallbackPolicy
也处理它。
回复:
What I would like to do is to pass in two handlers (
onFail(transaction)
which disposes the transaction andonSuccess(transaction)
which commits the transaction)
没有任何政策对成功提供特殊处理,但是:
3。有了 Polly,我怎样才能在整体失败时做一件事而在整体成功时做另一件事?
使用.ExecuteAndCapture(...)
. This returns a PolicyResult
with property .Outcome == OutcomeType.Successful
or OutcomeType.Failure
(and other info: see 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(); }