Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Make quick start samples consistent #1735

Merged
merged 6 commits into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
324 changes: 174 additions & 150 deletions README.md

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ResiliencePipeline pipeline = new ResiliencePipelineBuilder()
.Build(); // Builds the resilience pipeline

// Execute the pipeline asynchronously
await pipeline.ExecuteAsync(static async cancellationToken => { /*Your custom logic here */ }, cancellationToken);
await pipeline.ExecuteAsync(static async token => { /*Your custom logic goes here */ }, cancellationToken);
```
<!-- endSnippet -->

Expand All @@ -46,7 +46,7 @@ services.AddResiliencePipeline("my-pipeline", builder =>
});

// Build the service provider
IServiceProvider serviceProvider = services.BuildServiceProvider();
var serviceProvider = services.BuildServiceProvider();

// Retrieve ResiliencePipelineProvider that caches and dynamically creates the resilience pipelines
var pipelineProvider = serviceProvider.GetRequiredService<ResiliencePipelineProvider<string>>();
Expand All @@ -57,7 +57,7 @@ ResiliencePipeline pipeline = pipelineProvider.GetPipeline("my-pipeline");
// Execute the pipeline
await pipeline.ExecuteAsync(static async token =>
{
// Your custom logic here
// Your custom logic goes here
});
```
<!-- endSnippet -->
44 changes: 24 additions & 20 deletions docs/strategies/circuit-breaker.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,38 @@

<!-- snippet: circuit-breaker -->
```cs
// Add circuit breaker with default options.
// Circuit breaker with default options.
// See https://www.pollydocs.org/strategies/circuit-breaker#defaults for defaults.
new ResiliencePipelineBuilder().AddCircuitBreaker(new CircuitBreakerStrategyOptions());
var optionsDefaults = new CircuitBreakerStrategyOptions();

// Add circuit breaker with customized options:
//
// Circuit breaker with customized options:
// The circuit will break if more than 50% of actions result in handled exceptions,
// within any 10-second sampling duration, and at least 8 actions are processed.
new ResiliencePipelineBuilder().AddCircuitBreaker(new CircuitBreakerStrategyOptions
var optionsComplex = new CircuitBreakerStrategyOptions
{
FailureRatio = 0.5,
SamplingDuration = TimeSpan.FromSeconds(10),
MinimumThroughput = 8,
BreakDuration = TimeSpan.FromSeconds(30),
ShouldHandle = new PredicateBuilder().Handle<SomeExceptionType>()
});
};

// Handle specific failed results for HttpResponseMessage:
new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddCircuitBreaker(new CircuitBreakerStrategyOptions<HttpResponseMessage>
{
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<SomeExceptionType>()
.HandleResult(response => response.StatusCode == HttpStatusCode.InternalServerError)
});
var optionsShouldHandle = new CircuitBreakerStrategyOptions<HttpResponseMessage>
{
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<SomeExceptionType>()
.HandleResult(response => response.StatusCode == HttpStatusCode.InternalServerError)
};

// Monitor the circuit state, useful for health reporting:
var stateProvider = new CircuitBreakerStateProvider();
var optionsStateProvider = new CircuitBreakerStrategyOptions<HttpResponseMessage>
{
StateProvider = stateProvider
};

new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddCircuitBreaker(new() { StateProvider = stateProvider })
.Build();
var circuitState = stateProvider.CircuitState;

/*
CircuitState.Closed - Normal operation; actions are executed.
Expand All @@ -62,16 +62,20 @@ CircuitState.Isolated - Circuit is manually held open; actions are blocked.

// Manually control the Circuit Breaker state:
var manualControl = new CircuitBreakerManualControl();

new ResiliencePipelineBuilder()
.AddCircuitBreaker(new() { ManualControl = manualControl })
.Build();
var optionsManualControl = new CircuitBreakerStrategyOptions
{
ManualControl = manualControl
};

// Manually isolate a circuit, e.g., to isolate a downstream service.
await manualControl.IsolateAsync();

// Manually close the circuit to allow actions to be executed again.
await manualControl.CloseAsync();

// Add a circuit breaker strategy with a CircuitBreakerStrategyOptions{<TResult>} instance to the pipeline
new ResiliencePipelineBuilder().AddCircuitBreaker(optionsDefaults);
new ResiliencePipelineBuilder<HttpResponseMessage>().AddCircuitBreaker(optionsStateProvider);
```
<!-- endSnippet -->

Expand Down
72 changes: 36 additions & 36 deletions docs/strategies/fallback.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,48 @@

<!-- snippet: fallback -->
```cs
// Add a fallback/substitute value if an operation fails.
new ResiliencePipelineBuilder<UserAvatar>()
.AddFallback(new FallbackStrategyOptions<UserAvatar>
{
ShouldHandle = new PredicateBuilder<UserAvatar>()
.Handle<SomeExceptionType>()
.HandleResult(r => r is null),
FallbackAction = args => Outcome.FromResultAsValueTask(UserAvatar.Blank)
});
// A fallback/substitute value if an operation fails.
var optionsSubstitute = new FallbackStrategyOptions<UserAvatar>
martintmk marked this conversation as resolved.
Show resolved Hide resolved
{
ShouldHandle = new PredicateBuilder<UserAvatar>()
.Handle<SomeExceptionType>()
.HandleResult(r => r is null),
FallbackAction = static args => Outcome.FromResultAsValueTask(UserAvatar.Blank)
};

// Use a dynamically generated value if an operation fails.
new ResiliencePipelineBuilder<UserAvatar>()
.AddFallback(new FallbackStrategyOptions<UserAvatar>
var optionsFallbackAction = new FallbackStrategyOptions<UserAvatar>
{
ShouldHandle = new PredicateBuilder<UserAvatar>()
.Handle<SomeExceptionType>()
.HandleResult(r => r is null),
FallbackAction = static args =>
{
ShouldHandle = new PredicateBuilder<UserAvatar>()
.Handle<SomeExceptionType>()
.HandleResult(r => r is null),
FallbackAction = args =>
{
var avatar = UserAvatar.GetRandomAvatar();
return Outcome.FromResultAsValueTask(avatar);
}
});
var avatar = UserAvatar.GetRandomAvatar();
return Outcome.FromResultAsValueTask(avatar);
}
};

// Use a default or dynamically generated value, and execute an additional action if the fallback is triggered.
new ResiliencePipelineBuilder<UserAvatar>()
.AddFallback(new FallbackStrategyOptions<UserAvatar>
var optionsOnFallback = new FallbackStrategyOptions<UserAvatar>
{
ShouldHandle = new PredicateBuilder<UserAvatar>()
.Handle<SomeExceptionType>()
.HandleResult(r => r is null),
FallbackAction = static args =>
{
ShouldHandle = new PredicateBuilder<UserAvatar>()
.Handle<SomeExceptionType>()
.HandleResult(r => r is null),
FallbackAction = args =>
{
var avatar = UserAvatar.GetRandomAvatar();
return Outcome.FromResultAsValueTask(UserAvatar.Blank);
},
OnFallback = args =>
{
// Add extra logic to be executed when the fallback is triggered, such as logging.
return default; // Returns an empty ValueTask
}
});
var avatar = UserAvatar.GetRandomAvatar();
return Outcome.FromResultAsValueTask(UserAvatar.Blank);
},
OnFallback = static args =>
{
// Add extra logic to be executed when the fallback is triggered, such as logging.
return default; // Returns an empty ValueTask
}
};

// Add a fallback strategy with a FallbackStrategyOptions<TResult> instance to the pipeline
new ResiliencePipelineBuilder<UserAvatar>().AddFallback(optionsOnFallback);
```
<!-- endSnippet -->

Expand Down
54 changes: 27 additions & 27 deletions docs/strategies/hedging.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,41 @@ This strategy also supports multiple [concurrency modes](#concurrency-modes) for

<!-- snippet: hedging -->
```cs
// Add hedging with default options.
// Hedging with default options.
// See https://www.pollydocs.org/strategies/hedging#defaults for defaults.
new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddHedging(new HedgingStrategyOptions<HttpResponseMessage>());
var optionsDefaults = new HedgingStrategyOptions<HttpResponseMessage>();

// Add a customized hedging strategy that retries up to 3 times if the execution
// A customized hedging strategy that retries up to 3 times if the execution
// takes longer than 1 second or if it fails due to an exception or returns an HTTP 500 Internal Server Error.
new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddHedging(new HedgingStrategyOptions<HttpResponseMessage>
var optionsComplex = new HedgingStrategyOptions<HttpResponseMessage>
{
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<SomeExceptionType>()
.HandleResult(response => response.StatusCode == HttpStatusCode.InternalServerError),
MaxHedgedAttempts = 3,
Delay = TimeSpan.FromSeconds(1),
ActionGenerator = static args =>
{
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<SomeExceptionType>()
.HandleResult(response => response.StatusCode == HttpStatusCode.InternalServerError),
MaxHedgedAttempts = 3,
Delay = TimeSpan.FromSeconds(1),
ActionGenerator = args =>
{
Console.WriteLine("Preparing to execute hedged action.");
Console.WriteLine("Preparing to execute hedged action.");

// Return a delegate function to invoke the original action with the action context.
// Optionally, you can also create a completely new action to be executed.
return () => args.Callback(args.ActionContext);
}
});
// Return a delegate function to invoke the original action with the action context.
// Optionally, you can also create a completely new action to be executed.
return () => args.Callback(args.ActionContext);
}
};

// Subscribe to hedging events.
new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddHedging(new HedgingStrategyOptions<HttpResponseMessage>
var optionsOnHedging = new HedgingStrategyOptions<HttpResponseMessage>
{
OnHedging = static args =>
{
OnHedging = args =>
{
Console.WriteLine($"OnHedging: Attempt number {args.AttemptNumber}");
return default;
}
});
Console.WriteLine($"OnHedging: Attempt number {args.AttemptNumber}");
return default;
}
};

// Add a hedging strategy with a HedgingStrategyOptions<TResult> instance to the pipeline
new ResiliencePipelineBuilder<HttpResponseMessage>().AddHedging(optionsDefaults);
```
<!-- endSnippet -->

Expand Down
11 changes: 6 additions & 5 deletions docs/strategies/rate-limiter.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ new ResiliencePipelineBuilder()

// Create a rate limiter that allows 100 executions per minute.
new ResiliencePipelineBuilder()
.AddRateLimiter(new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions
{
PermitLimit = 100,
Window = TimeSpan.FromMinutes(1)
}));
.AddRateLimiter(new SlidingWindowRateLimiter(
new SlidingWindowRateLimiterOptions
{
PermitLimit = 100,
Window = TimeSpan.FromMinutes(1)
}));
```
<!-- endSnippet -->

Expand Down
38 changes: 21 additions & 17 deletions docs/strategies/retry.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,32 @@

<!-- snippet: Retry -->
```cs
// Add retry using the default options.
// Retry using the default options.
// See https://www.pollydocs.org/strategies/retry#defaults for defaults.
new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions());
var optionsDefaults = new RetryStrategyOptions();

// For instant retries with no delay
new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
var optionsNoDelay = new RetryStrategyOptions
{
Delay = TimeSpan.Zero
});
};

// For advanced control over the retry behavior, including the number of attempts,
// delay between retries, and the types of exceptions to handle.
new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
var optionsComplex = new RetryStrategyOptions
{
ShouldHandle = new PredicateBuilder().Handle<SomeExceptionType>(),
BackoffType = DelayBackoffType.Exponential,
UseJitter = true, // Adds a random factor to the delay
MaxRetryAttempts = 4,
Delay = TimeSpan.FromSeconds(3),
});
};

// To use a custom function to generate the delay for retries
new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
var optionsDelayGenerator = new RetryStrategyOptions
{
MaxRetryAttempts = 2,
DelayGenerator = args =>
DelayGenerator = static args =>
{
var delay = args.AttemptNumber switch
{
Expand All @@ -52,12 +52,12 @@ new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
// but the API also supports asynchronous implementations.
return new ValueTask<TimeSpan?>(delay);
}
});
};

// To extract the delay from the result object
new ResiliencePipelineBuilder<HttpResponseMessage>().AddRetry(new RetryStrategyOptions<HttpResponseMessage>
var optionsExtractDelay = new RetryStrategyOptions<HttpResponseMessage>
{
DelayGenerator = args =>
DelayGenerator = static args =>
{
if (args.Outcome.Result is HttpResponseMessage responseMessage &&
TryGetDelay(responseMessage, out TimeSpan delay))
Expand All @@ -68,26 +68,30 @@ new ResiliencePipelineBuilder<HttpResponseMessage>().AddRetry(new RetryStrategyO
// Returning null means the retry strategy will use its internal delay for this attempt.
return new ValueTask<TimeSpan?>((TimeSpan?)null);
}
});
};

// To get notifications when a retry is performed
new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
var optionsOnRetry = new RetryStrategyOptions
{
MaxRetryAttempts = 2,
OnRetry = args =>
OnRetry = static args =>
{
Console.WriteLine("OnRetry, Attempt: {0}", args.AttemptNumber);

// Event handlers can be asynchronous; here, we return an empty ValueTask.
return default;
}
});
};

// To keep retrying indefinitely or until success use int.MaxValue.
new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
var optionsIndefiniteRetry = new RetryStrategyOptions
{
MaxRetryAttempts = int.MaxValue,
});
};

// Add a retry strategy with a RetryStrategyOptions{<TResult>} instance to the pipeline
new ResiliencePipelineBuilder().AddRetry(optionsDefaults);
new ResiliencePipelineBuilder<HttpResponseMessage>().AddRetry(optionsExtractDelay);
```
<!-- endSnippet -->

Expand Down
Loading