Scroll Top

StarCellar E04: Applying resilience strategies with Apizr

SCE04_gif

Episode 04 of an Apizr walkthrough building a MAUI app requesting a backend API.

Apizr is a Refit based web api client manager, but resilient (retry, connectivity, cache, auth, log, priority, etc…).

This episode is about resilience strategies (aka policies).

APIZR

If you’re new to Apizr, you shoud know that it’s based on Refit and aims to provide many more features on top of it, like retry handling, connectivity check, cache management, authentication handling, priority management, and so on… It’s here to help me to don’t repeat myself into each and every projects while dealing with api request calls and resilience needs.

Get the big picture by reading the documentation:

Read - Documentation

Feel free to browse code, tests and samples and maybe to submit PRs or ideas:

Browse - Source

Don’t forget the YouTube Channel Playlist about Apizr:

Watch - Tutorials

The starcellar series

The StarCellar walkthrough series is built thanks to multiple episodes, each with a dedicated source code branch, blog post and playlist video.

Feel free to fork the project and start from the main branch, so that you could follow this tutorial coding by yourself. If you do so, don’t forget to run the API through a Dev Tunnel and to update the MAUI app’s base address.

the starcellar episode 04

The current episode is covered by this video:

applaying resilience strategies Without Apizr

First, the Without.Apizr project as usual!

Start by referencing NuGet package:

  • Microsoft.Extensions.Http.Resilience

Now open the MauiProgram class and scroll to the Refit registration part.

There, add the following extension methods to both RefitClient registrations:

.AddStandardResilienceHandler()

Here we provide the built-in resilience handler provided by Microsoft to the Refit’s HttpClient request pipeline.

This handler will obviously handle any managed failures with its default configuration.

You can run the app and see that there’s now some retries into the VS output in case of network failure.

Configuring resilience strategies With Apizr

Now the With.Apizr project!

Start by referencing the same NuGet package:

  • Microsoft.Extensions.Http.Resilience

Now open the MauiProgram class and scroll to the Apizr registration part.

There, add the following extension methods to both Apizr registrations, right into the ConfigureHttpClientBuilder method:

.ConfigureHttpClientBuilder(clientBuilder => clientBuilder
.AddStandardResilienceHandler()));

Here we provide the built-in resilience handler provided by Microsoft to the Apizr’s HttpClient request pipeline.

This handler will obviously handle any managed failures with its default configuration.

You can run the app and see that there’s now some retries into the VS output in case of network failure.

Adjusting standard resilience handler’s configuration

In both With.Apizr or Without.Apizr projects, you definitly can adjust the standard resilience handler’s configuration.

Here is how to do that by adjusting app settings:

"ResilienceOptions": {
    "Retry": {
        "BackoffType": "Exponential",
        "UseJitter": true,
        "MaxRetryAttempts": 3
    }
}

Then providing the settings:

.ConfigureHttpClientBuilder(builder => builder
.AddStandardResilienceHandler(configuration.GetSection("ResilienceOptions")))

Or even manually:

.ConfigureHttpClientBuilder(clientBuilder => clientBuilder
    .AddStandardResilienceHandler(resilienceOptions =>
    {
        resilienceOptions.CircuitBreaker.MinimumThroughput = 10;
        // and so on...
    }))
Applying strategies by attribute design

You may want to apply specific resilience strategies to specific requests only.

Apizr let you do that by attribute design.

First, you have to define your strategies by building a pipeline:

var resiliencePipelineBuilder = new ResiliencePipelineBuilder<HttpResponseMessage>()
    .AddRetry(
        new RetryStrategyOptions<HttpResponseMessage>
        {
            ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
                .Handle<HttpRequestException>()
                .HandleResult(response =>
                    response.StatusCode is >= HttpStatusCode.InternalServerError
                        or HttpStatusCode.RequestTimeout),
            Delay = TimeSpan.FromSeconds(1),
            MaxRetryAttempts = 3,
            UseJitter = true,
            BackoffType = DelayBackoffType.Exponential
        });

Then just register it into your container:

// (Polly) Add the resilience pipeline with its key to your container
services.AddResiliencePipeline<string, HttpResponseMessage>("TransientHttpError",
    builder => builder.AddPipeline(resiliencePipelineBuilder.Build()));

And finally activate it by attribute:

[BaseAddress("/wines"), Log, ResiliencePipeline("TransientHttpError")]
public interface ICellarApi
{
    [Get("/")]
    Task<IEnumerable<Wine>> GetWinesAsync();

    [Get("/{id}")]
    Task<Wine> GetWineDetailsAsync(Guid id);

    [Post("/")]
    Task<Wine> CreateWineAsync(Wine item);
    
    [Put("/{id}")]
    Task UpdateWineAsync(Guid id, Wine item);
    
    [Delete("/{id}")]
    Task DeleteWineAsync(Guid id);
}

Here we’re telling Apizr to apply such a pipeline to any ICellarApi request.

get more of it

Feel free to ask me anything on twitter, or opening a discussion, issue or PR on GitHub.

Again, it’s basically all built for my own use and motivated by my needs. But it’s live on Nuget and opened to all so feel free to contribute.

Apizr brings many more features so you should head to the next episode to continue your walkthrough path.

Specialized since 2013 in cross-platform applications development for iOS, Android and Windows, using technologies such as Microsoft Xamarin and Microsoft Azure. Initially focused, since 2005, on development, then administration of Customer Relationship Management systems, mainly around solutions such as Microsoft SharePoint and Microsoft Dynamics CRM.

Related Posts

Leave a comment