Cannot get Polly to work with Collapse Request

Viewed 433

Im really struggling with Polly

I have the following package references running in a .NET Core Web Api Application

<PackageReference Include="Polly" Version="7.2.1" />
<PackageReference Include="Polly.Caching.Distributed" Version="3.0.1" />
<PackageReference Include="Polly.Caching.Memory" Version="3.0.2" />
<PackageReference Include="Polly.Contrib.DuplicateRequestCollapser" Version="0.2.1" />
<PackageReference Include="Polly.Extensions.Http" Version="3.0.0" />

My task is to use Polly to "Squash multiple requests into a single request"

For this I am trying to use

https://github.com/Polly-Contrib/Polly.Contrib.DuplicateRequestCollapser

As a starting point I used

https://nodogmablog.bryanhogan.net/2018/11/caching-in-polly-6-and-the-httpclientfactory/#:~:text=Polly%20allows%20you%20to%20cache,you%20define%20polices%20in%20startup.

This gave me a startup of

using System;
using System.Net.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.Caching;
using Polly.Caching.Memory;
using Polly.Registry;

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMemoryCache();
        services.AddSingleton<IAsyncCacheProvider, MemoryCacheProvider>();

        IPolicyRegistry<string> registry = services.AddPolicyRegistry();

        services.AddHttpClient("RemoteServer", client =>
        {
            client.BaseAddress = new Uri("http://localhost:5000/api/");
            client.DefaultRequestHeaders.Add("Accept", "application/json");
        }).AddPolicyHandlerFromRegistry(PolicySelector);

        //services.AddSingleton<IRequestService, RequestService>();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    private IAsyncPolicy<HttpResponseMessage> PolicySelector(IReadOnlyPolicyRegistry<string> policyRegistry,
        HttpRequestMessage httpRequestMessage)
    {
        // you could have some logic to select the right policy
        // see https://nodogmablog.bryanhogan.net/2018/07/polly-httpclientfactory-and-the-policy-registry-choosing-the-right-policy-based-on-the-http-request/
        return policyRegistry.Get<IAsyncPolicy<HttpResponseMessage>>("CachingPolicy");
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAsyncCacheProvider cacheProvider, IPolicyRegistry<string> registry)
    {
        CachePolicy<HttpResponseMessage> cachePolicy = Policy.CacheAsync<HttpResponseMessage>(cacheProvider, TimeSpan.FromSeconds(30));
        registry.Add("CachingPolicy", cachePolicy);

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();
    }
}

The sample works but as soon as I add the DuplicateRequestCollapser to the project

I had a compilation error on

CachePolicy<HttpResponseMessage> cachePolicy = Policy.CacheAsync<HttpResponseMessage>(cacheProvider, TimeSpan.FromSeconds(30));

That was easy to fix I changed to

AsyncCachePolicy<HttpResponseMessage> cachePolicy = Policy.CacheAsync<HttpResponseMessage>(cacheProvider, TimeSpan.FromSeconds(30));

Now when I run I get the error

System.TypeLoadException: 'Method 'TryGet' in type 'Polly.Caching.Memory.MemoryCacheProvider' from 
assembly 'Polly.Caching.Memory, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c8a3ffc3f8f825cc' 
does not have an implementation.'

Its tough trying to find clear tutorials for Poly, especially the duplicate request collapser

Can anyone tell me what I am doing wrong?

This is not working just from adding the package and I havent even started on integrating the duplicate request collapser itself! The documentation is not easy to follow

Paul

1 Answers

As it turned out that the root cause was the usage of an older version of the package.

Even though it was stated that the 3.0.2 version has been used

<PackageReference Include="Polly.Caching.Memory" Version="3.0.2" />

The error itself tells that the 2.0.0 was in use

System.TypeLoadException: 'Method 'TryGet' in type 'Polly.Caching.Memory.MemoryCacheProvider' from assembly 'Polly.Caching.Memory, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c8a3ffc3f8f825cc' does not have an implementation.'

After upgrading to 3.0.2 the exception has been gone.


Even though most of the packages require 7.1.1 or greater Polly version
the Polly.Contrib.DuplicateRequestCollapser has a quite strict dependency requirement:

Polly (>= 7.2.0 && < 8.0.0)

At the time of writing there are only two Polly verions which suffice this requirement: 7.2.0 and 7.2.1


So, the moral of this fable is that package versions should be double checked.

Related