Skip to content

Commit b355c51

Browse files
committed
Add some GetPolicy extensions to get by Type. Add documentation.
1 parent 567fe35 commit b355c51

File tree

4 files changed

+200
-72
lines changed

4 files changed

+200
-72
lines changed

src/Foundatio/Resilience/IResiliencePolicy.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,25 @@
44

55
namespace Foundatio.Resilience;
66

7+
/// <summary>
8+
/// Defines a contract for executing actions with resilience policies, such as retries, circuit breakers, or timeouts.
9+
/// </summary>
710
public interface IResiliencePolicy
811
{
12+
/// <summary>
13+
/// Executes the specified asynchronous action using the resilience policy.
14+
/// </summary>
15+
/// <param name="action">The asynchronous action to execute. The <see cref="CancellationToken"/> parameter allows the action to observe cancellation requests.</param>
16+
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
17+
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
918
ValueTask ExecuteAsync(Func<CancellationToken, ValueTask> action, CancellationToken cancellationToken = default);
19+
20+
/// <summary>
21+
/// Executes the specified asynchronous action using the resilience policy and returns a result.
22+
/// </summary>
23+
/// <typeparam name="T">The type of the result returned by the action.</typeparam>
24+
/// <param name="action">The asynchronous action to execute. The <see cref="CancellationToken"/> parameter allows the action to observe cancellation requests.</param>
25+
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
26+
/// <returns>A <see cref="ValueTask{T}"/> representing the asynchronous operation and its result.</returns>
1027
ValueTask<T> ExecuteAsync<T>(Func<CancellationToken, ValueTask<T>> action, CancellationToken cancellationToken = default);
1128
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,21 @@
11
namespace Foundatio.Resilience;
22

3+
/// <summary>
4+
/// Provides methods for retrieving and managing resilience policies, such as retry, circuit breaker, or timeout policies.
5+
/// </summary>
36
public interface IResiliencePolicyProvider
47
{
8+
/// <summary>
9+
/// Gets the default resilience policy.
10+
/// </summary>
11+
/// <returns>The default <see cref="IResiliencePolicy"/> instance.</returns>
512
IResiliencePolicy GetDefaultPolicy();
13+
14+
/// <summary>
15+
/// Gets a named resilience policy.
16+
/// </summary>
17+
/// <param name="name">The name of the policy to retrieve.</param>
18+
/// <param name="useDefault">If true, returns the default policy if the named policy is not found; otherwise, returns null.</param>
19+
/// <returns>The <see cref="IResiliencePolicy"/> instance, or null if not found and <paramref name="useDefault"/> is false.</returns>
620
IResiliencePolicy GetPolicy(string name, bool useDefault = true);
721
}

src/Foundatio/Resilience/ResiliencePolicyExtensions.cs

Lines changed: 96 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -11,117 +11,122 @@ public static class ResiliencePolicyExtensions
1111
/// <summary>
1212
/// Gets a resilience policy for the specified type from the provider, or creates a new default configuration one if not found.
1313
/// </summary>
14-
/// <param name="provider"></param>
15-
/// <param name="logger"></param>
16-
/// <param name="timeProvider"></param>
17-
/// <typeparam name="T"></typeparam>
18-
/// <returns></returns>
14+
/// <typeparam name="T">The type for which to get the policy.</typeparam>
15+
/// <param name="provider">The resilience policy provider.</param>
16+
/// <param name="logger">Optional logger to use for the created policy if not found in the provider.</param>
17+
/// <param name="timeProvider">Optional time provider to use for the created policy if not found in the provider.</param>
18+
/// <returns>The resolved or newly created <see cref="IResiliencePolicy"/>.</returns>
1919
public static IResiliencePolicy GetPolicy<T>(this IResiliencePolicyProvider provider, ILogger logger = null, TimeProvider timeProvider = null)
2020
{
21-
IResiliencePolicy policy = provider?.GetPolicy(typeof(T).GetFriendlyTypeName(), false);
22-
return policy ?? GetDefaultPolicy(provider, null, logger, timeProvider);
21+
return GetPolicy(provider, [typeof(T)], null, logger, timeProvider);
2322
}
2423

2524
/// <summary>
2625
/// Gets a resilience policy for the specified type from the provider, or creates a new one using the fallback builder if not found.
2726
/// </summary>
28-
/// <param name="provider"></param>
29-
/// <param name="fallbackBuilder"></param>
30-
/// <param name="logger"></param>
31-
/// <param name="timeProvider"></param>
32-
/// <typeparam name="T"></typeparam>
33-
/// <returns></returns>
27+
/// <typeparam name="T">The type for which to get the policy.</typeparam>
28+
/// <param name="provider">The resilience policy provider.</param>
29+
/// <param name="fallbackBuilder">An action to configure the fallback <see cref="IResiliencePolicy"/> if not found in the provider.</param>
30+
/// <param name="logger">Optional logger to use for the created policy if not found in the provider.</param>
31+
/// <param name="timeProvider">Optional time provider to use for the created policy if not found in the provider.</param>
32+
/// <returns>The resolved or newly created <see cref="IResiliencePolicy"/>.</returns>
3433
public static IResiliencePolicy GetPolicy<T>(this IResiliencePolicyProvider provider, Action<ResiliencePolicyBuilder> fallbackBuilder, ILogger logger = null, TimeProvider timeProvider = null)
3534
{
36-
IResiliencePolicy policy = provider?.GetPolicy(typeof(T).GetFriendlyTypeName(), false);
37-
return policy ?? GetDefaultPolicy(provider, fallbackBuilder, logger, timeProvider);
35+
return GetPolicy(provider, [typeof(T)], fallbackBuilder, logger, timeProvider);
3836
}
3937

4038
/// <summary>
4139
/// Gets a resilience policy by checking the specified types in order from the provider, or creates a new default configuration one if not found.
4240
/// </summary>
43-
/// <param name="provider"></param>
44-
/// <param name="logger"></param>
45-
/// <param name="timeProvider"></param>
46-
/// <typeparam name="T1"></typeparam>
47-
/// <typeparam name="T2"></typeparam>
48-
/// <returns></returns>
41+
/// <typeparam name="T1">The first type to check for a policy.</typeparam>
42+
/// <typeparam name="T2">The second type to check for a policy.</typeparam>
43+
/// <param name="provider">The resilience policy provider.</param>
44+
/// <param name="logger">Optional logger to use for the created policy if not found in the provider.</param>
45+
/// <param name="timeProvider">Optional time provider to use for the created policy if not found in the provider.</param>
46+
/// <returns>The resolved or newly created <see cref="IResiliencePolicy"/>.</returns>
4947
public static IResiliencePolicy GetPolicy<T1, T2>(this IResiliencePolicyProvider provider, ILogger logger = null, TimeProvider timeProvider = null)
5048
{
51-
if (provider != null)
52-
{
53-
IResiliencePolicy policy = provider.GetPolicy(typeof(T1).GetFriendlyTypeName(), false) ?? provider.GetPolicy(typeof(T2).GetFriendlyTypeName(), false);
54-
if (policy != null)
55-
return policy;
56-
}
57-
58-
return GetDefaultPolicy(provider, null, logger, timeProvider);
49+
return GetPolicy(provider, [typeof(T1), typeof(T2)], null, logger, timeProvider);
5950
}
6051

6152
/// <summary>
6253
/// Gets a resilience policy by checking the specified types in order from the provider, or creates a new one using the fallback builder if not found.
6354
/// </summary>
64-
/// <param name="provider"></param>
65-
/// <param name="fallbackBuilder"></param>
66-
/// <param name="logger"></param>
67-
/// <param name="timeProvider"></param>
68-
/// <typeparam name="T1"></typeparam>
69-
/// <typeparam name="T2"></typeparam>
70-
/// <returns></returns>
55+
/// <typeparam name="T1">The first type to check for a policy.</typeparam>
56+
/// <typeparam name="T2">The second type to check for a policy.</typeparam>
57+
/// <param name="provider">The resilience policy provider.</param>
58+
/// <param name="fallbackBuilder">An action to configure the fallback <see cref="IResiliencePolicy"/> if not found in the provider.</param>
59+
/// <param name="logger">Optional logger to use for the created policy if not found in the provider.</param>
60+
/// <param name="timeProvider">Optional time provider to use for the created policy if not found in the provider.</param>
61+
/// <returns>The resolved or newly created <see cref="IResiliencePolicy"/>.</returns>
7162
public static IResiliencePolicy GetPolicy<T1, T2>(this IResiliencePolicyProvider provider, Action<ResiliencePolicyBuilder> fallbackBuilder, ILogger logger = null, TimeProvider timeProvider = null)
7263
{
73-
if (provider != null)
74-
{
75-
IResiliencePolicy policy = provider.GetPolicy(typeof(T1).GetFriendlyTypeName(), false) ?? provider.GetPolicy(typeof(T2).GetFriendlyTypeName(), false);
76-
if (policy != null)
77-
return policy;
78-
}
79-
80-
return GetDefaultPolicy(provider, fallbackBuilder, logger, timeProvider);
64+
return GetPolicy(provider, [typeof(T1), typeof(T2)], fallbackBuilder, logger, timeProvider);
8165
}
8266

8367
/// <summary>
8468
/// Gets a resilience policy by checking the specified types in order from the provider, or creates a new default configuration one if not found.
8569
/// </summary>
86-
/// <param name="provider"></param>
87-
/// <param name="logger"></param>
88-
/// <param name="timeProvider"></param>
89-
/// <typeparam name="T1"></typeparam>
90-
/// <typeparam name="T2"></typeparam>
91-
/// <typeparam name="T3"></typeparam>
92-
/// <returns></returns>
70+
/// <typeparam name="T1">The first type to check for a policy.</typeparam>
71+
/// <typeparam name="T2">The second type to check for a policy.</typeparam>
72+
/// <typeparam name="T3">The third type to check for a policy.</typeparam>
73+
/// <param name="provider">The resilience policy provider.</param>
74+
/// <param name="logger">Optional logger to use for the created policy if not found in the provider.</param>
75+
/// <param name="timeProvider">Optional time provider to use for the created policy if not found in the provider.</param>
76+
/// <returns>The resolved or newly created <see cref="IResiliencePolicy"/>.</returns>
9377
public static IResiliencePolicy GetPolicy<T1, T2, T3>(this IResiliencePolicyProvider provider, ILogger logger = null, TimeProvider timeProvider = null)
9478
{
95-
if (provider != null)
96-
{
97-
IResiliencePolicy policy = provider.GetPolicy(typeof(T1).GetFriendlyTypeName(), false) ?? provider.GetPolicy(typeof(T2).GetFriendlyTypeName(), false) ?? provider.GetPolicy(typeof(T3).GetFriendlyTypeName(), false);
98-
if (policy != null)
99-
return policy;
100-
}
101-
102-
return GetDefaultPolicy(provider, null, logger, timeProvider);
79+
return GetPolicy(provider, [typeof(T1), typeof(T2), typeof(T3)], null, logger, timeProvider);
10380
}
10481

10582
/// <summary>
10683
/// Gets a resilience policy by checking the specified types in order from the provider, or creates a new one using the fallback builder if not found.
10784
/// </summary>
108-
/// <param name="provider"></param>
109-
/// <param name="fallbackBuilder"></param>
110-
/// <param name="logger"></param>
111-
/// <param name="timeProvider"></param>
112-
/// <typeparam name="T1"></typeparam>
113-
/// <typeparam name="T2"></typeparam>
114-
/// <typeparam name="T3"></typeparam>
115-
/// <returns></returns>
85+
/// <typeparam name="T1">The first type to check for a policy.</typeparam>
86+
/// <typeparam name="T2">The second type to check for a policy.</typeparam>
87+
/// <typeparam name="T3">The third type to check for a policy.</typeparam>
88+
/// <param name="provider">The resilience policy provider.</param>
89+
/// <param name="fallbackBuilder">An action to configure the fallback <see cref="IResiliencePolicy"/> if not found in the provider.</param>
90+
/// <param name="logger">Optional logger to use for the created policy if not found in the provider.</param>
91+
/// <param name="timeProvider">Optional time provider to use for the created policy if not found in the provider.</param>
92+
/// <returns>The resolved or newly created <see cref="IResiliencePolicy"/>.</returns>
11693
public static IResiliencePolicy GetPolicy<T1, T2, T3>(this IResiliencePolicyProvider provider, Action<ResiliencePolicyBuilder> fallbackBuilder, ILogger logger = null, TimeProvider timeProvider = null)
11794
{
118-
IResiliencePolicy policy;
95+
return GetPolicy(provider, [typeof(T1), typeof(T2), typeof(T3)], fallbackBuilder, logger, timeProvider);
96+
}
97+
98+
/// <summary>
99+
/// Gets a resilience policy for the specified type from the provider, or creates a new default configuration one if not found.
100+
/// </summary>
101+
/// <param name="provider">The resilience policy provider.</param>
102+
/// <param name="targetType">The type for which to get the policy.</param>
103+
/// <param name="logger">Optional logger to use for the created policy if not found in the provider.</param>
104+
/// <param name="timeProvider">Optional time provider to use for the created policy if not found in the provider.</param>
105+
/// <returns>The resolved or newly created <see cref="IResiliencePolicy"/>.</returns>
106+
public static IResiliencePolicy GetPolicy(this IResiliencePolicyProvider provider, Type targetType, ILogger logger = null, TimeProvider timeProvider = null)
107+
{
108+
return GetPolicy(provider, [targetType], null, logger, timeProvider);
109+
}
119110

111+
/// <summary>
112+
/// Gets a resilience policy by checking the specified types in order from the provider, or creates a new one using the fallback builder if not found.
113+
/// </summary>
114+
/// <param name="provider">The resilience policy provider.</param>
115+
/// <param name="targetTypes">The types to check for a policy, in order.</param>
116+
/// <param name="fallbackBuilder">An action to configure the fallback <see cref="IResiliencePolicy"/> if not found in the provider.</param>
117+
/// <param name="logger">Optional logger to use for the created policy if not found in the provider.</param>
118+
/// <param name="timeProvider">Optional time provider to use for the created policy if not found in the provider.</param>
119+
/// <returns>The resolved or newly created <see cref="IResiliencePolicy"/>.</returns>
120+
public static IResiliencePolicy GetPolicy(this IResiliencePolicyProvider provider, Type[] targetTypes, Action<ResiliencePolicyBuilder> fallbackBuilder, ILogger logger = null, TimeProvider timeProvider = null)
121+
{
120122
if (provider != null)
121123
{
122-
policy = provider.GetPolicy(typeof(T1).GetFriendlyTypeName(), false) ?? provider.GetPolicy(typeof(T2).GetFriendlyTypeName(), false) ?? provider.GetPolicy(typeof(T3).GetFriendlyTypeName(), false);
123-
if (policy != null)
124-
return policy;
124+
foreach (var targetType in targetTypes)
125+
{
126+
IResiliencePolicy policy = provider.GetPolicy(targetType.GetFriendlyTypeName(), false);
127+
if (policy != null)
128+
return policy;
129+
}
125130
}
126131

127132
return GetDefaultPolicy(provider, fallbackBuilder, logger, timeProvider);
@@ -141,11 +146,23 @@ private static IResiliencePolicy GetDefaultPolicy(IResiliencePolicyProvider prov
141146
return policy;
142147
}
143148

149+
/// <summary>
150+
/// Gets the <see cref="IResiliencePolicyProvider"/> from the specified object if it implements <see cref="IHaveResiliencePolicyProvider"/>.
151+
/// </summary>
152+
/// <param name="target">The object to retrieve the policy provider from.</param>
153+
/// <returns>The <see cref="IResiliencePolicyProvider"/> if available; otherwise, <c>null</c>.</returns>
144154
public static IResiliencePolicyProvider GetResiliencePolicyProvider(this object target)
145155
{
146156
return target is IHaveResiliencePolicyProvider accessor ? accessor.ResiliencePolicyProvider : null;
147157
}
148158

159+
/// <summary>
160+
/// Executes the specified asynchronous action using the given resilience policy.
161+
/// </summary>
162+
/// <param name="policy">The resilience policy to use for execution.</param>
163+
/// <param name="action">The asynchronous action to execute.</param>
164+
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
165+
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
149166
public static ValueTask ExecuteAsync(this IResiliencePolicy policy, Func<ValueTask> action, CancellationToken cancellationToken = default)
150167
{
151168
if (policy == null)
@@ -157,6 +174,14 @@ public static ValueTask ExecuteAsync(this IResiliencePolicy policy, Func<ValueTa
157174
return policy.ExecuteAsync(_ => action(), cancellationToken);
158175
}
159176

177+
/// <summary>
178+
/// Executes the specified asynchronous action using the given resilience policy and returns a result.
179+
/// </summary>
180+
/// <typeparam name="T">The type of the result returned by the action.</typeparam>
181+
/// <param name="policy">The resilience policy to use for execution.</param>
182+
/// <param name="action">The asynchronous action to execute.</param>
183+
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
184+
/// <returns>A <see cref="ValueTask{T}"/> representing the asynchronous operation and its result.</returns>
160185
public static ValueTask<T> ExecuteAsync<T>(this IResiliencePolicy policy, Func<ValueTask<T>> action, CancellationToken cancellationToken = default)
161186
{
162187
if (policy == null)

0 commit comments

Comments
 (0)