Rougamo.Retry
5.0.0
dotnet add package Rougamo.Retry --version 5.0.0
NuGet\Install-Package Rougamo.Retry -Version 5.0.0
<PackageReference Include="Rougamo.Retry" Version="5.0.0" />
paket add Rougamo.Retry --version 5.0.0
#r "nuget: Rougamo.Retry, 5.0.0"
// Install Rougamo.Retry as a Cake Addin #addin nuget:?package=Rougamo.Retry&version=5.0.0 // Install Rougamo.Retry as a Cake Tool #tool nuget:?package=Rougamo.Retry&version=5.0.0
Rougamo.Retry
δΈζ | English
Use Rougamo.Retry
dotnet add package Rougamo.Retry
Quick Start
// Any exception thrown by M1Async will be retried once
[Retry]
public async Task M1Async()
{
}
// Any exception thrown by M2 will be retried, up to three times
[Retry(3)]
public void M2()
{
}
// When M3Async throws IOException or TimeoutException, it will retry up to five times
[Retry(5, typeof(IOException), typeof(TimeoutException))]
public static async ValueTask M3Async()
{
}
// If the exception matching logic is complex, you can customize the type to implement IExceptionMatcher
class ExceptionMatcher : IExceptionMatcher
{
public bool Match(Exception e) => true;
}
[Retry(2, typeof(ExceptionMatcher))]
public static void M4()
{
}
// If the number of retries is also fixed, you can customize the type to implement IRetryDefinition
class RetryDefinition : IRetryDefinition
{
public int Times => 3;
public bool Match(Exception e) => true;
}
[Retry(typeof(RetryDefinition))]
public void M5()
{
}
Record Exception
Sometimes we also want to record the exception information when the exception throws. At this time, we can implement IRecordable
.
// Implemente the IRecordableMatcher will not include the definition of the number of retries
class RecordableMatcher : IRecordableMatcher
{
public bool Match(Exception e) => true;
public void TemporaryFailed(ExceptionContext context)
{
// The current method still has the number of retries
// The current exception can be obtained through context.Exception
}
public void UltimatelyFailed(ExceptionContext context)
{
// The number of retries for the current method has been used up, and finally failed
// The current exception can be obtained through context.Exception
}
}
[Retry(3, typeof(RecordableMatcher))]
public async ValueTask M6Async()
{
}
// Implemente the IRecordableRetryDefinition will include the definition of the number of retries
class RecordableRetryDefinition : IRecordableRetryDefinition
{
public int Times => 3;
public bool Match(Exception e) => true;
public void TemporaryFailed(ExceptionContext context)
{
// The current method still has the number of retries
// The current exception can be obtained through context.Exception
}
public void UltimatelyFailed(ExceptionContext context)
{
// The number of retries for the current method has been used up, and finally failed
// The current exception can be obtained through context.Exception
}
}
[Retry(typeof(RecordableRetryDefinition))]
public async Task M7Async()
{
}
Asynchronous Exception Handling
Version 5.0 added asynchronous exception handling methods TemporaryFailedAsync
and UltimatelyFailedAsync
to the IRecordable
interface for netstandard2.1, facilitating asynchronous operations. The asynchronous methods were only added for netstandard2.1 because it supports default interface methods. Therefore, the ISyncRecordable
and IAsyncRecordable
interfaces have implemented default asynchronous and synchronous methods respectively, for easier use. Additionally, since IRecordableMatcher
and IRecordableRetryDefinition
also implement the IRecordable
interface, they have been provided with implementations of the default synchronous/asynchronous methods as well.
Dependency Injection
The methods for recording exceptions are varied, with writing to logs being one of the most commonly used. Many logging frameworks rely on dependency injection support, whereas Rougamo.Retry
does not come with built-in dependency injection capabilities. The types defined above will use parameterless constructors to create their objects. However, Rougamo.Retry
offers a method to alter the object creation process via Resolver.Set(ResolverFactory)
. It is recommended to combine this with DependencyInjection.StaticAccessor
to set up dependency injection.
// Modify the object creation method to obtain object instances from PinnedScope.ScopedServices
Resolver.Set(t => PinnedScope.ScopedServices!.GetRequiredService(t));
// Subsequent initialization should be completed according to the series of documentation for DependencyInjection.StaticAccessor, based on your project type.
Rougamo.Retry.AspNetCore
<font color=red>Note that Rougamo.Retry.AspNetCore
is no longer recommended, and the related NuGet package will be marked as obsolete. It is suggested to follow the introduction provided in the Dependency Injection section and use DependencyInjection.StaticAccessor
to set up dependency injection.</font>
// 1. Define a type that implements IRecordableMatcher or IRecordableRetryDefinition, then inject and use ILogger
class RecordableRetryDefinition : IRecordableRetryDefinition
{
private readonly ILogger _logger;
public RecordableRetryDefinition(ILogger<RecordableRetryDefinition> logger)
{
_logger = logger;
}
public int Times => 3;
public bool Match(Exception e) => true;
public void TemporaryFailed(ExceptionContext context)
{
// The current method still has the number of retries
_logger.LogDebug(context.Exception, string.Empty);
}
public void UltimatelyFailed(ExceptionContext context)
{
// The number of retries for the current method has been used up, and finally failed
_logger.LogError(context.Exception, string.Empty);
}
}
// 2. Initialize in Startup
class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 2.1. Replace the retry factory to IServiceProvider
services.AddAspNetRetryFactory();
// 2.2. Register RecordableRetryDefinition
services.AddTransient<RecordableRetryDefinition>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// 2.3. Register the middleware of Rougamo.Retry.AspNetCore. Try to put it in the front, otherwise if the previous middlewares uses Rougamo.Retry, then an exception may occur.
app.UseRetryFactory();
}
}
// 3. Apply RetryAttribute to methods
[Retry(typeof(RecordableRetryDefinition))]
public static async Task M8Async()
{
}
Rougamo.Retry.GeneralHost
<font color=red>Note that Rougamo.Retry.GeneralHost
is no longer recommended, and the related NuGet package will be marked as obsolete. It is suggested to follow the introduction provided in the Dependency Injection section and use DependencyInjection.StaticAccessor
to set up dependency injection.</font>
In addition to AspNetCore, we may also create some general programs. At this time, we need to reference Rougamo.Retry.GeneralHost
.
// 1. Define a type that implements IRecordableMatcher or IRecordableRetryDefinition, then inject and use ILogger
class RecordableMatcher : IRecordableMatcher
{
private readonly ILogger _logger;
public RecordableMatcher(ILogger<RecordableMatcher> logger)
{
_logger = logger;
}
public bool Match(Exception e) => true;
public void TemporaryFailed(ExceptionContext context)
{
// The current method still has the number of retries
_logger.LogDebug(context.Exception, string.Empty);
}
public void UltimatelyFailed(ExceptionContext context)
{
// The number of retries for the current method has been used up, and finally failed
_logger.LogError(context.Exception, string.Empty);
}
}
// 2. Initialize in ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
// 2.1. Replace the retry factory to IServiceProvider
services.AddRetryFactory();
// 2.2. Register RecordableMatcher
services.AddTransient<RecordableMatcher>();
}
// 3. Apply RetryAttribute to methods
[Retry(2, typeof(RecordableMatcher))]
public static void M9()
{
}
Unified record Exception
If the logic for recording exceptions is generic, then we can simplify this operation with RecordRetryAttribute
and IRecordable
.
// 1. Define a type that implements IRecordable
class Recordable : IRecordable
{
private readonly ILogger _logger;
public Recordable(ILogger<Recordable> logger)
{
_logger = logger;
}
public void TemporaryFailed(ExceptionContext context)
{
// The current method still has the number of retries
_logger.LogDebug(context.Exception, string.Empty);
}
public void UltimatelyFailed(ExceptionContext context)
{
// The number of retries for the current method has been used up, and finally failed
_logger.LogError(context.Exception, string.Empty);
}
}
// 2. Register Recordable. Note that only additional steps are shown here, if you use Rougamo.Retry.AspNetCore or Rougamo.Retry.GeneralHost, then you also need to complete the initialization of these components
public void ConfigureServices(IServiceCollection services)
{
services.AddRecordable<Recordable>();
}
// 3. Apply RecordRetryAttribute to methods
[RecordRetry]
public async Task M10Async() { }
[RecordRetry(3)]
public void M11() { }
[RecordRetry(5, typeof(IOException), typeof(TimeoutException))]
public static async ValueTask M12Async() { }
class ExceptionMatcher : IExceptionMatcher
{
public bool Match(Exception e) => true;
}
[RecordRetry(2, typeof(ExceptionMatcher))]
public static void M13() { }
class RetryDefinition : IRetryDefinition
{
public int Times => 3;
public bool Match(Exception e) => true;
}
[RecordRetry(typeof(RetryDefinition))]
public void M14()
{
}
Attention
- When using
RetryAttribute
andRecordRetryAttribute
, the current project must directly referenceRougamo.Retry
, not indirect reference, otherwise the code cannot be woven.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Rougamo.Fody (>= 5.0.0 && < 6.0.0)
-
.NETStandard 2.1
- Rougamo.Fody (>= 5.0.0 && < 6.0.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Rougamo.Retry:
Package | Downloads |
---|---|
Rougamo.Retry.AspNetCore
Catch the specific exceptions and re-execute the method, weave IL code at complie time. |
|
Rougamo.Retry.GeneralHost
Catch the specific exceptions and re-execute the method, weave IL code at complie time. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
5.0.0 | 128 | 12/15/2024 |
4.0.0 | 205 | 8/13/2024 |
4.0.0-priview-1723529391 | 158 | 8/13/2024 |
4.0.0-priview-1723528975 | 125 | 8/13/2024 |
0.1.0 | 2,650 | 3/1/2023 |
0.1.0-beta1 | 203 | 3/1/2023 |
0.1.0-beta | 196 | 2/28/2023 |
0.1.0-alpha | 152 | 2/25/2023 |