Polly v8 resilience pipelines for Hangfire — retry, timeout, and circuit-breaker for IBackgroundJobClient.Enqueue and Schedule.
Hangfire's built-in retry applies to job execution on the server side. It does not protect the client side — when your app calls Enqueue() or Schedule() and the backing job store (Redis, SQL Server, etc.) is temporarily unavailable, you get an unhandled BackgroundJobClientException or DistributedLockTimeoutException.
PollyHangfire fills that gap.
dotnet add package PollyHangfire
`csharp services.AddPollyHangfire(pipeline => pipeline .AddRetry(new RetryStrategyOptions { MaxRetryAttempts = 3, Delay = TimeSpan.FromMilliseconds(500), BackoffType = DelayBackoffType.Exponential, ShouldHandle = HangfireTransientErrors.IsTransient, }) .AddTimeout(TimeSpan.FromSeconds(10)));
// Requires IBackgroundJobClient to already be registered (e.g. via services.AddHangfire(...)) public class OrderService(ResilientBackgroundJobClient jobs) { public void PlaceOrder(Order order) => jobs.Enqueue(p => p.ProcessAsync(order)); } `
`csharp IBackgroundJobClient client = new BackgroundJobClient();
var resilient = client.WithPolly(pipeline => pipeline.AddRetry(new RetryStrategyOptions { MaxRetryAttempts = 3, Delay = TimeSpan.FromMilliseconds(500), BackoffType = DelayBackoffType.Exponential, ShouldHandle = HangfireTransientErrors.IsTransient, }));
resilient.Enqueue(s => s.SendWelcomeEmailAsync(userId)); resilient.Schedule(r => r.GenerateAsync(reportId), TimeSpan.FromHours(1)); `
| Method | Description |
|---|---|
| Enqueue(Expression) | Enqueue fire-and-forget job |
| Enqueue(Expression<Action>) | Enqueue typed fire-and-forget job |
| Schedule(Expression, TimeSpan) | Schedule delayed job |
| Schedule(Expression<Action>, TimeSpan) | Schedule typed delayed job |
| Execute(Func) | Execute arbitrary function in pipeline |
HangfireTransientErrors.IsTransient handles:
| Exception | Reason |
|---|---|
| BackgroundJobClientException | Job store temporarily unavailable |
| DistributedLockTimeoutException | Distributed lock acquisition failed |
| TimeoutException | Store connection or command timed out |
| TaskCanceledException | Operation cancelled |
et6.0 · et8.0 · et9.0
| Package | Wraps |
|---|---|
| PollyEFCore | Entity Framework Core DbContext |
| PollyDapper | Dapper IDbConnection |
| PollyMongo | MongoDB IMongoCollection |
| PollyAzureBlob | Azure Blob Storage BlobContainerClient |
| PollyNpgsql | Npgsql PostgreSQL NpgsqlConnection |
| PollySqlClient | System.Data.SqlClient SqlConnection |
| PollyCosmosDb | Azure Cosmos DB CosmosClient |
| PollyGrpc | gRPC channel calls |
| PollyRabbitMQ | RabbitMQ IModel channel |
| PollyAzureServiceBus | Azure Service Bus sender/receiver |
| PollyRedis | StackExchange.Redis IDatabase |
| PollyMediatR | MediatR IMediator |
| PollyOpenAI | OpenAI ChatClient |
| PollyHealthChecks | ASP.NET Core health checks |
| PollyBackoff | Pre-built backoff pipelines |
| PollyChaos | Chaos engineering helpers |
| PollyKafka | Confluent Kafka producer/consumer |
| PollySignalR | SignalR HubConnection |
| PollyRateLimiter | .NET rate limiting middleware |
| PollyElasticsearch | Elastic.Clients.Elasticsearch |
| PollyAzureKeyVault | Azure Key Vault SecretClient |
| PollyAzureEventHub | Azure Event Hubs producer |
| PollySendGrid | SendGrid email client |
| PollyMassTransit | MassTransit IBus |
| PollyAzureTableStorage | Azure Table Storage TableClient |
| PollyMailKit | MailKit SMTP email client |
| PollyAzureQueueStorage | Azure Queue Storage QueueClient |
The author of this package is available for consulting on Polly v8 resilience, Azure cloud architecture, and clean .NET design.
→ solidqualitysolutions.com · LinkedIn
MIT © Justin Bannister