Resilience refers to a system's ability to recover gracefully from failures, handle unexpected situations, and continue delivering what it's supposed to do. To achieve this, engineers use key resilience patterns like circuit breakers, retries, fallbacks, and throttling.
Adding resilience into a codebase usually requires writing boilerplate code, which is often tedious, unproductive, and error-prone.
Let's see how Metalama helps.
With Polly
Polly is the go-to library for implementing resilience in .NET. It implements the most-used policies, is actively maintained, and there is probably no need to reinvent the wheel.
However, adding Polly to your code can still require some boilerplate code: you still need to pull dependencies and wrap all methods into delegate calls—for each method.
With Metalama, you can add Polly without any boilerplate.
Benefits
Compared to adding Polly manually, adding it with Metalama has the following benefits:
- Clean code: There's no need to wrap your code in a delegate call, so it remains crystal clear and is easier to maintain.
- Easily modify the pattern: You can easily replace Polly with another library or remove it altogether if you want.
Example
You can create a [AddPolicy]
Metalama aspect that pulls the Polly dependency and wraps your method into a delegate code:
public class CalculatorService
{
[AddPolly( "MyPolicy" )]
public int Add( int a, int b )
{
// Your code here
return a + b;
}
}
See this commented example to learn how to create such aspects.
Show me my transformed code!
Here is what the [AddPolly]
aspect may do to your code.
internal class CalculatorService
{
private ILogger _logger;
private IPolicyFactory _policyFactory;
public CalculatorService(ILogger<RemoteCalculator> logger, IPolicyFactory? policyFactory)
{
this._logger = logger;
this._policyFactory = policyFactory;
}
public int Add(int a, int b)
{
object? ExecuteCore()
{
try
{
// Your code here.
return a + b;
}
catch (Exception e)
{
_logger.LogWarning(
$"CalculatorService.Add(a = {{{a}}}, b = {{{b}}}) has failed: {e.Message}");
throw;
}
}
var policy = _policyFactory.GetPolicy(PolicyKind.Retry);
return (int)policy.Execute(ExecuteCore);
}
}
Resources
- Example: Implementing an auto-retry aspect that uses Polly
- Blog: 5 practical ways to add Polly to your application
Without Polly
You can, of course, create exception-handling aspects without Polly. See these examples to get some inspiration.