Multiple retry policies' knowledge of each other #2201
-
I have multiple retry policies with different options in the same pipeline. The inner policies handle specific exceptions while the outer policy handles a broader set of exceptions. If an outcome is handled by an inner policy and exceeds its How do you configure an outer retry policy to skip an outcome if an inner retry policy has already handled it? Ideally, the outer policy should not be required to know the criteria for the inner policies. Unfortunately, the contract of |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
Have you tried passing some state using a resilience context that the outer handlers can inspect that the inner handlers could write to? |
Beta Was this translation helpful? Give feedback.
-
Thanks @martincostello that's a pretty good idea. I had the idea to introduce the concept of a "strategy group," going to give it a try: using Polly;
using Polly.Retry;
/// <summary>
/// Extensions of <see cref="ResilienceStrategy"/> and related types.
/// </summary>
public static class ResilienceStrategyExtensions
{
/// <summary>
/// Assigns a group for the strategy.
/// </summary>
/// <remarks>
/// Configures the retry to skip outcomes that have already been handled by a different strategy
/// within the same group.
/// </remarks>
/// <typeparam name="T">The strategy result type.</typeparam>
/// <param name="options">The retry strategy options.</param>
/// <param name="groupId">An identifier for the group.</param>
public static void SetStrategyGroup<T>(this RetryStrategyOptions<T> options, string groupId)
{
ArgumentNullException.ThrowIfNull(options, nameof(options));
ArgumentNullException.ThrowIfNull(groupId, nameof(groupId));
var handledKey = new ResiliencePropertyKey<object?>($"group-{groupId}-handled");
var shouldHandle = options.ShouldHandle;
var onRetry = options.OnRetry;
options.ShouldHandle =
args =>
{
if (args.AttemptNumber == 0 && args.Context.Properties.TryGetValue(handledKey, out _))
{
// Skip if another strategy has already handled this outcome.
return new(false);
}
return shouldHandle(args);
};
options.OnRetry =
args =>
{
args.Context.Properties.Set(handledKey, null);
return onRetry?.Invoke(args) ?? default;
};
}
}
|
Beta Was this translation helpful? Give feedback.
Have you tried passing some state using a resilience context that the outer handlers can inspect that the inner handlers could write to?