ToolWheel.Extensions.JobManager.Resilience 1.0.0-preview6

This is a prerelease version of ToolWheel.Extensions.JobManager.Resilience.
dotnet add package ToolWheel.Extensions.JobManager.Resilience --version 1.0.0-preview6
                    
NuGet\Install-Package ToolWheel.Extensions.JobManager.Resilience -Version 1.0.0-preview6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ToolWheel.Extensions.JobManager.Resilience" Version="1.0.0-preview6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ToolWheel.Extensions.JobManager.Resilience" Version="1.0.0-preview6" />
                    
Directory.Packages.props
<PackageReference Include="ToolWheel.Extensions.JobManager.Resilience" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ToolWheel.Extensions.JobManager.Resilience --version 1.0.0-preview6
                    
#r "nuget: ToolWheel.Extensions.JobManager.Resilience, 1.0.0-preview6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ToolWheel.Extensions.JobManager.Resilience@1.0.0-preview6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ToolWheel.Extensions.JobManager.Resilience&version=1.0.0-preview6&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=ToolWheel.Extensions.JobManager.Resilience&version=1.0.0-preview6&prerelease
                    
Install as a Cake Tool

ToolWheel.Extensions.JobManager.Resilience

Adds resilience patterns to the ToolWheel Job Manager: circuit breaker, configurable retry strategies and per-operation/total timeouts.

Package Info

Property Value
Target Framework net8.0
NuGet Package ID ToolWheel.Extensions.JobManager.Resilience
Project Reference ToolWheel.Extensions.JobManager.Abstractions
Package Dependencies Microsoft.Extensions.Logging.Abstractions

Auto Configuration

This package ships JobManagerResilienceConfigurator implementing IAutoFeatureConfigurator. When AddJobManager() scans loaded assemblies it automatically:

  1. Registers IRetryService, ICircuitBreakerService and ITimeoutService as singletons.
  2. Adds CircuitBreakerMiddleware, TotalTimeoutMiddleware, RetryMiddleware and OperationTimeoutMiddleware to the pipeline (in that order).
  3. Adds CircuitBreakerCondition as an IExecutionCondition.

No manual registration is required – referencing the package is sufficient.

Per-job configuration flows through each feature's Apply method called by IJobService.Add:

Feature Apply calls
RetryFeature IRetryService.UpdateRetryConfiguration
CircuitBreakerFeature ICircuitBreakerService.UpdateConfiguration
TimeoutFeature ITimeoutService.UpdateConfiguration

Fluent Configuration

All resilience features are reached via a single .Resilience() entry point:

jobs.Add("import-job", worker.RunImport)
    .Name("Data Import")
    .Enabled()
    .Resilience()
        .WithCircuitBreaker(failureThreshold: 3, openDuration: TimeSpan.FromMinutes(2))
        .WithExponentialRetry(maxAttempts: 3, initialDelay: TimeSpan.FromSeconds(2))
        .WithTimeout(t => t
            .WithOperationTimeout(TimeSpan.FromSeconds(30))
            .WithTotalTimeout(TimeSpan.FromMinutes(2)))
    .JobBuilder;

Circuit Breaker

Prevents a job from starting when the circuit is open (too many recent failures). The circuit transitions through three states:

State Behaviour
Closed Execution is allowed normally.
Open Execution is blocked. CircuitBreakerCondition returns NotReady.
Half-Open One probe execution is allowed to test recovery.

Configuration

// Shorthand
.WithCircuitBreaker(failureThreshold: 5, openDuration: TimeSpan.FromMinutes(1))

// Full configuration
.WithCircuitBreaker(cb => cb
    .WithFailureThreshold(3)
    .WithOpenDuration(TimeSpan.FromSeconds(30))
    .WithSuccessThreshold(2)                        // successes in half-open to close
    .WithSamplingDuration(TimeSpan.FromMinutes(5))  // rolling failure window
    .OnlyFor(typeof(HttpRequestException), typeof(TimeoutException)))

How It Works

  1. CircuitBreakerCondition blocks execution when the circuit is open.
  2. CircuitBreakerMiddleware records the outcome of each execution (RecordFailure / RecordSuccess).
  3. After FailureThreshold failures the circuit opens.
  4. After OpenDuration elapses, the circuit transitions to half-open and allows one probe.
  5. After SuccessThreshold consecutive successes in half-open state, the circuit closes.

Retry

Automatically retries a failed job execution with configurable delay strategies.

Configuration

// Exponential backoff
.WithExponentialRetry(maxAttempts: 3, initialDelay: TimeSpan.FromSeconds(1))

// Linear delay
.WithLinearRetry(maxAttempts: 5, delay: TimeSpan.FromSeconds(10))

// Full configuration
.WithRetry(r => r
    .WithMaxAttempts(4)
    .WithStrategy(RetryStrategy.Exponential)
    .WithInitialDelay(TimeSpan.FromSeconds(2))
    .WithMaxDelay(TimeSpan.FromMinutes(5))
    .WithBackoffMultiplier(2.0)
    .OnlyFor(typeof(HttpRequestException)))

Retry Strategies

Strategy Delay calculation
Linear Constant delay between every attempt.
Exponential initialDelay × multiplier^attempt, capped at MaxDelay.

Retries stop when the maximum number of attempts is reached, a non-retryable exception is thrown, or the total timeout (if configured) is exceeded.


Timeout

Two independent timeouts can be configured:

Timeout Scope Middleware
OperationTimeout Each individual attempt (including retries). OperationTimeoutMiddleware
TotalTimeout All attempts combined. TotalTimeoutMiddleware

Configuration

.WithTimeout(t => t
    .WithOperationTimeout(TimeSpan.FromSeconds(30))
    .WithTotalTimeout(TimeSpan.FromMinutes(2))
    .WithTimeoutException(true))  // throw JobTimeoutException instead of OperationCanceledException

Middleware Execution Order

The pipeline order is fixed by JobManagerResilienceConfigurator:

Request
  └─ CircuitBreakerMiddleware       (1 – blocks if circuit is open)
       └─ TotalTimeoutMiddleware    (2 – deadline for all attempts)
            └─ RetryMiddleware      (3 – retry loop)
                 └─ OperationTimeoutMiddleware  (4 – timeout per attempt)
                      └─ Job TargetMethod

API Reference

Extension Method

IJobDescriptionResilienceBuilder Resilience(this IJobDescriptionBuilder builder)

Services

Interface Description
ICircuitBreakerService Manages circuit states. Supports CanExecute, RecordSuccess, RecordFailure, Reset, UpdateConfiguration.
IRetryService Stores and retrieves retry configurations per job.
ITimeoutService Stores and retrieves timeout configurations per job.

Features

Type Stores
CircuitBreakerFeature FailureThreshold, OpenDuration, SuccessThreshold, SamplingDuration, FailureExceptionTypes.
RetryFeature MaxRetryAttempts, InitialDelay, Strategy, MaxDelay, BackoffMultiplier, RetryOnExceptionTypes.
TimeoutFeature OperationTimeout, TotalTimeout, ThrowTimeoutException.

Conditions

Type Blocks when
CircuitBreakerCondition The circuit breaker for the job is in the open state.

Middleware

Type Purpose
CircuitBreakerMiddleware Records success/failure outcomes and manages state transitions.
RetryMiddleware Retries failed executions with the configured delay strategy.
OperationTimeoutMiddleware Cancels an individual attempt after the configured timeout.
TotalTimeoutMiddleware Cancels all further retries after the total timeout deadline.
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-preview6 55 3/26/2026
1.0.0-preview5 57 2/21/2026