-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Polly v8 API feedback #1365
Comments
@martincostello, great feedback, let's try to address some of these :)
This was intentional, so we can support strongly-typed access to values. However, we can also expose it with implicit conversion. Is there any reason you are not using the
I think we can expand the functionality to allow sharing
I'll try to rewrite this in a Polly V8 way tomorrow. I believe we have a support for this scenario by using the builders and dynamic strategy creation. But let me confirm that tomorrow. |
Basically laziness - I was expecting to be able to just quickly use the indexer on a string to get a string back (I was replacing some code that was using the operating key). Not shown in the code above I just made myself an extension method to do it via the Get and Set methods. It just seemed a lot more verbose for that use case. internal static class PollyExtensions
{
private static readonly ResiliencePropertyKey<string> OperationKeyKey = new("OperationKey");
internal static string GetOperationKey(this ResilienceContext context)
{
if (!context.Properties.TryGetValue(OperationKeyKey, out string operationKey))
{
operationKey = "Unknown";
}
return operationKey;
}
internal static void SetOperationKey(this ResilienceContext context, string operationKey)
=> context.Properties.Set(OperationKeyKey, operationKey);
} |
How about we allow: resilienceContext.Properties.Get<string>("my-key"); It will be just convenience method that creates Would that simplify your use-case? |
Yeah I think that would be a good compromise - I think in my case it just seemed extra complicated compared to v7 because I was replacing a string-string pair in the first place, rather than some other type(s). Essentially the |
@martincostello I tried to rewrite your example using the Polly V8 way in #1366. Please let me know if that works for you. |
Regarding this code: internal static class PollyExtensions
{
private static readonly ResiliencePropertyKey<string> OperationKeyKey = new("OperationKey");
internal static string GetOperationKey(this ResilienceContext context)
{
if (!context.Properties.TryGetValue(OperationKeyKey, out string operationKey))
{
operationKey = "Unknown";
}
return operationKey;
}
internal static void SetOperationKey(this ResilienceContext context, string operationKey)
=> context.Properties.Set(OperationKeyKey, operationKey);
} Regarding We might introduce |
We use it in logging. For example with the v7 code: [LoggerMessage(8, LogLevel.Information, "{PolicyWrapKey}:{PolicyKey} at {OperationKey} execution timed out after {Timeout} with exception.")]
public static partial void TimeoutWithException(ILogger logger, Exception exception, string policyWrapKey, string policyKey, string operationKey, TimeSpan timeout); I'm fine with losing the wrap keys and the type of policy can be inferred from the context, but we'd still want to know which endpoint's policy is firing without having to read the stack trace to work it out. |
What are the examples of the values you are assigning to it? Does it have high cardinality? (for example you are generating guids for it) Basically, I am asking if we can include it in the metrics by default. |
They're values similar to this: This particular application has dependencies on 4 other applications it calls over HTTP, and the maximum number of distinct HTTP operations exposed by any one them is 5. For example:
|
Ok, I think it makes sense to add it to Polly V8 as it can add valuable information to the telemetry. I'll make a note that the property should have low cardinality. edit:
I don't think logs as the one above would be required after this change. |
I've created a sandbox app and the relevant tests based on our internal application here: https://github.com/martincostello/polly-sandbox It illustrates how Polly v7 is integrated today into our HTTP client request processing. I'll create a branch based on the v8 API from my internal branch later this afternoon that makes the same changes I made that lead to this issue including the latest changes from alpha.5 and see how far I get. Once that's done there'll be something more concrete to base a migration path around. |
This is great! We can also use it as a case-study on how the migration from V7 to V8 might look like. |
Looking at your sample I think we need to add support for And using it to cache the rate limiter strategy. Rather than hacking around caching the rate limiter strategies, we can use the built-in PartitionedRateLimiter that does exactly the same thing. To add this support to Polly we can just introduce the public sealed class ResilienceRateLimiter
{
/// <summary>
/// Creates an instance of <see cref="ResilienceRateLimiter"/> from <paramref name="rateLimiter"/>.
/// </summary>
/// <param name="rateLimiter">The rate limiter instance.</param>
/// <returns>An instance of <see cref="ResilienceRateLimiter"/>.</returns>
public static ResilienceRateLimiter Create(RateLimiter rateLimiter) => new(Guard.NotNull(rateLimiter), null);
/// <summary>
/// Creates an instance of <see cref="ResilienceRateLimiter"/> from partitioned <paramref name="rateLimiter"/>.
/// </summary>
/// <param name="rateLimiter">The rate limiter instance.</param>
/// <returns>An instance of <see cref="ResilienceRateLimiter"/>.</returns>
public static ResilienceRateLimiter Create(PartitionedRateLimiter<ResilienceContext> rateLimiter) => new(null, Guard.NotNull(rateLimiter));
} And use it in public class RateLimiterStrategyOptions : ResilienceStrategyOptions
{
// other properties
public ResilienceRateLimiter? RateLimiter { get; set; }
} This way we could preserve having only a single options and still have the possibility to expand the @martincostello Shall I give this a go? edit: updated the API to reuse the |
Sure that makes sense to me 👍 |
The branch using 8.0.0-alpha.5 is here: https://github.com/martincostello/polly-sandbox/tree/polly-v8 The tests are now all passing, but it's mostly a "make it work" conversion using resilience strategies - I haven't attempted to properly v8-ify the code yet, like using the built-in reload support. A few further observations now it's working.
|
I've applied the changes and fixes back to the original internal application and that's all building with passing tests now too (again, not v8-ified yet). |
True, we should note this. The flow is now similar to
I would say yes. If the jitter is supported for We can either expand the enum with new members, or simplify it and introduce |
Can you create a PR so I can add comments to it for reference? |
|
|
I've pushed the latest changes to my sandbox app. I'll likely do some more work on it on Friday. Based on the current state, there's a few more pieces of feedback.
|
Can you add a comment to the API review? We can discuss this addition there. |
I think we've tackled everything I raised here as of alpha.8. |
I've spent a few hours today upgrading an internal application which uses Polly from the v7 policies to v8 resilience strategies and encountered a number of rough edges and/or difficulties. This issue catalogs those at a high-level for discussion as to whether or not these are issues or missing functionality that we would wish to fix/add as part of the v8 release. I can add more concrete details/repro if needed for the specific items.
ResilienceProperties
has a dictionary indexer for reading and writing properties, but it is an explicit interface definition so requires casting to a dictionary to use. It would be much more convenient to make it implicit so you can do things likearguments.Properties["foo"]
.CircuitBreakerManualControl
across multiple strategies - we have a use case where we manually isolate circuit breakers and it isn't possible to have a single instance available to any circuit breaker strategy to observe (thing similarly to sharing aCancellationToken
on multiple operations). I've tried pooling them and iterating through the set when I want to open/close them, but this doesn't seem to work with what I've tried so far.It might be that in some cases I'm just using the new API wrong, rather than their being issues. There might also be cases where I need to re-approach how Polly is used in a more fundamental way - for example Policies are currently created on-demand, which makes it non-trivial to put them in DI. Similarly, the pay configuration changes are handled to recreate the cached policies in a policy registry would need to be reworked to use the new reloading mechanism if using the DI integration as well.
I'll do some more work on this tomorrow application with v8 and try and get the application's tests passing again - at the moment I've got issues with circuit breakers as well as retries (not shown above) not working properly.
/cc @martintmk
The text was updated successfully, but these errors were encountered: