2

I have a refit client (IMyRefitClient) that returns

Task<ApiResponse<ADomainModel>>

I can't inject this refit client in Program.cs with HostBuilder.ConfigureServices because the url isn't known until runtime. Therefore, I'm using a factory class like:

return RestService.For<IMyRefitClient>(hostUrl);

I know how to add a policy in ConfigureServices. It would look like:

services.AddRefitClient<IMyRefitClient>()
        .AddPolicyHandler(PollyHelpers.GetRetryPolicy());

Is there a way that I can add this policy when using the factory class?

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
Jack
  • 237
  • 1
  • 4
  • 14
  • 2
    You can define or retrieve the policies inside the `IMyRefitClient` implementation. If you want to register the policies into the DI then take a look at the [`PolicyRegistry`](https://github.com/App-vNext/Polly/wiki/PolicyRegistry) class and `IReadOnlyPolicyRegistry` interface. – Peter Csala Oct 05 '21 at 07:06
  • Did the proposed classes/interfaces solve your problem? Shall I leave a post to further elaborate? – Peter Csala Oct 08 '21 at 06:19
  • 1
    Using those has indeed worked, thanks @PeterCsala! – Jack Oct 12 '21 at 14:28
  • Awesome. Shall I leave a post to close this question? – Peter Csala Oct 12 '21 at 14:29
  • @PeterCsala I'm not too familiar with stackoverflow etiquette with accepted answer gone so I'm not sure. – Jack Oct 12 '21 at 17:30

1 Answers1

2

Polly has a concept of PolicyRegister, which is basically a IEnumerable<KeyValuePair<string, IsPolicy>> collection.

So, it is a container where you can register policies with arbitrary names:

var register = new PolicyRegistry()
{
    { "CB_aware_Retry", GetRetryPolicy() },
    { "500_aware_CB", GetCircuitBreakerPolicy() },
    { "Retry_CB_combined", Policy.WrapAsync(GetRetryPolicy(), GetCircuitBreakerPolicy()) }
};

On the ServiceCollection you can register a new container or an existing one:

services.AddPolicyRegistry(registry)

You can access the policies by relying on the IReadOnlyPolicyRegistry:

public class MyRefitClient 
{
    private readonly IAsyncPolicy<ApiResponse<ADomainModel>>> combined;
    public MyRefitClient(..., IReadOnlyPolicyRegistry<string> registry, ...)
    {
       ...
       combined = registry.Get<IAsyncPolicy<ApiResponse<ADomainModel>>>>("Retry_CB_combined");
    } 
}    
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
  • Still confused on how to use this with Refit. Would using PolicyRegistry require getting the policy and wrapping it around every Refit call? For example, `policy.Execute(() => refitService.getCustomers(...))` – ShrimpCrackers Nov 03 '22 at 10:58
  • 1
    @ShrimpCrackers Yes, the above code requires you to explicitly call the `Execute`/`ExecuteAsync` methods. If you can register your Refit client inside your `ConfigureServices` with `AddRefitClient` then you can call `AddPolicyHandler`. With that approach the underlying `DelegatingHandler` will call the `Execute`/`ExecuteAsync` on your behalf. – Peter Csala Nov 03 '22 at 11:42