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 3 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
272 changes: 138 additions & 134 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 -->
30 changes: 15 additions & 15 deletions docs/strategies/circuit-breaker.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@
new ResiliencePipelineBuilder().AddCircuitBreaker(new CircuitBreakerStrategyOptions());

// Add 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
new ResiliencePipelineBuilder().AddCircuitBreaker(new()
{
FailureRatio = 0.5,
SamplingDuration = TimeSpan.FromSeconds(10),
Expand All @@ -38,20 +37,20 @@ new ResiliencePipelineBuilder().AddCircuitBreaker(new CircuitBreakerStrategyOpti
});

// 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)
});
new ResiliencePipelineBuilder<HttpResponseMessage>().AddCircuitBreaker(new()
{
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<SomeExceptionType>()
.HandleResult(response => response.StatusCode == HttpStatusCode.InternalServerError)
});

// Monitor the circuit state, useful for health reporting:
var stateProvider = new CircuitBreakerStateProvider();

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

/*
CircuitState.Closed - Normal operation; actions are executed.
Expand All @@ -63,9 +62,10 @@ 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();
new ResiliencePipelineBuilder().AddCircuitBreaker(new()
{
ManualControl = manualControl
});

// Manually isolate a circuit, e.g., to isolate a downstream service.
await manualControl.IsolateAsync();
Expand Down
67 changes: 32 additions & 35 deletions docs/strategies/fallback.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,44 @@
<!-- 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)
});
new ResiliencePipelineBuilder<UserAvatar>().AddFallback(new FallbackStrategyOptions<UserAvatar>
{
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>
new ResiliencePipelineBuilder<UserAvatar>().AddFallback(new()
{
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>
new ResiliencePipelineBuilder<UserAvatar>().AddFallback(new()
{
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
}
});
```
<!-- endSnippet -->

Expand Down
44 changes: 21 additions & 23 deletions docs/strategies/hedging.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,32 @@ new ResiliencePipelineBuilder<HttpResponseMessage>()

// Add 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>
new ResiliencePipelineBuilder<HttpResponseMessage>().AddHedging(new()
{
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>
new ResiliencePipelineBuilder<HttpResponseMessage>().AddHedging(new()
{
OnHedging = static args =>
{
OnHedging = args =>
{
Console.WriteLine($"OnHedging: Attempt number {args.AttemptNumber}");
return default;
}
});
Console.WriteLine($"OnHedging: Attempt number {args.AttemptNumber}");
return default;
}
});
```
<!-- endSnippet -->

Expand Down
17 changes: 7 additions & 10 deletions docs/strategies/rate-limiter.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,17 @@ Further reading:
```cs
// Add rate limiter with default options.
// See https://www.pollydocs.org/strategies/rate-limiter#defaults for defaults.
new ResiliencePipelineBuilder()
.AddRateLimiter(new RateLimiterStrategyOptions());
new ResiliencePipelineBuilder().AddRateLimiter(new RateLimiterStrategyOptions());

// Create a rate limiter to allow a maximum of 100 concurrent executions and a queue of 50.
new ResiliencePipelineBuilder()
.AddConcurrencyLimiter(100, 50);
new ResiliencePipelineBuilder().AddConcurrencyLimiter(100, 50);

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

Expand Down
18 changes: 9 additions & 9 deletions docs/strategies/retry.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions());

// For instant retries with no delay
new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
new ResiliencePipelineBuilder().AddRetry(new()
peter-csala marked this conversation as resolved.
Show resolved Hide resolved
{
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
new ResiliencePipelineBuilder().AddRetry(new()
{
ShouldHandle = new PredicateBuilder().Handle<SomeExceptionType>(),
BackoffType = DelayBackoffType.Exponential,
Expand All @@ -36,10 +36,10 @@ new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
});

// To use a custom function to generate the delay for retries
new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
new ResiliencePipelineBuilder().AddRetry(new()
{
MaxRetryAttempts = 2,
DelayGenerator = args =>
DelayGenerator = static args =>
{
var delay = args.AttemptNumber switch
{
Expand All @@ -55,9 +55,9 @@ new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
});

// To extract the delay from the result object
new ResiliencePipelineBuilder<HttpResponseMessage>().AddRetry(new RetryStrategyOptions<HttpResponseMessage>
new ResiliencePipelineBuilder<HttpResponseMessage>().AddRetry(new()
{
DelayGenerator = args =>
DelayGenerator = static args =>
{
if (args.Outcome.Result is HttpResponseMessage responseMessage &&
TryGetDelay(responseMessage, out TimeSpan delay))
Expand All @@ -71,10 +71,10 @@ new ResiliencePipelineBuilder<HttpResponseMessage>().AddRetry(new RetryStrategyO
});

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

Expand All @@ -84,7 +84,7 @@ new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
});

// To keep retrying indefinitely or until success use int.MaxValue.
new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions
new ResiliencePipelineBuilder().AddRetry(new()
{
MaxRetryAttempts = int.MaxValue,
});
Expand Down
46 changes: 21 additions & 25 deletions docs/strategies/timeout.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,35 @@
```cs
// Add timeout using the default options.
// See https://www.pollydocs.org/strategies/timeout#defaults for defaults.
new ResiliencePipelineBuilder()
.AddTimeout(new TimeoutStrategyOptions());
new ResiliencePipelineBuilder().AddTimeout(new TimeoutStrategyOptions());
martincostello marked this conversation as resolved.
Show resolved Hide resolved

// To add a timeout with a custom TimeSpan duration
new ResiliencePipelineBuilder()
.AddTimeout(TimeSpan.FromSeconds(3));
new ResiliencePipelineBuilder().AddTimeout(TimeSpan.FromSeconds(3));

// To add a timeout using a custom timeout generator function
new ResiliencePipelineBuilder()
.AddTimeout(new TimeoutStrategyOptions
new ResiliencePipelineBuilder().AddTimeout(new TimeoutStrategyOptions
{
TimeoutGenerator = static args =>
{
TimeoutGenerator = args =>
{
// Note: the timeout generator supports asynchronous operations
return new ValueTask<TimeSpan>(TimeSpan.FromSeconds(123));
}
});
// Note: the timeout generator supports asynchronous operations
return new ValueTask<TimeSpan>(TimeSpan.FromSeconds(123));
}
});

// To add a timeout and listen for timeout events
new ResiliencePipelineBuilder()
.AddTimeout(new TimeoutStrategyOptions
new ResiliencePipelineBuilder().AddTimeout(new TimeoutStrategyOptions
{
TimeoutGenerator = static args =>
{
TimeoutGenerator = args =>
{
// Note: the timeout generator supports asynchronous operations
return new ValueTask<TimeSpan>(TimeSpan.FromSeconds(123));
},
OnTimeout = args =>
{
Console.WriteLine($"{args.Context.OperationKey}: Execution timed out after {args.Timeout.TotalSeconds} seconds.");
return default;
}
});
// Note: the timeout generator supports asynchronous operations
return new ValueTask<TimeSpan>(TimeSpan.FromSeconds(123));
},
OnTimeout = static args =>
{
Console.WriteLine($"{args.Context.OperationKey}: Execution timed out after {args.Timeout.TotalSeconds} seconds.");
return default;
}
});
```
<!-- endSnippet -->

Expand Down
17 changes: 7 additions & 10 deletions src/Polly.RateLimiting/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,16 @@ See [the documentation](https://www.pollydocs.org/strategies/rate-limiter) for m
```cs
// Add rate limiter with default options.
// See https://www.pollydocs.org/strategies/rate-limiter#defaults for defaults.
new ResiliencePipelineBuilder()
.AddRateLimiter(new RateLimiterStrategyOptions());
new ResiliencePipelineBuilder().AddRateLimiter(new RateLimiterStrategyOptions());

// Create a rate limiter to allow a maximum of 100 concurrent executions and a queue of 50.
new ResiliencePipelineBuilder()
.AddConcurrencyLimiter(100, 50);
new ResiliencePipelineBuilder().AddConcurrencyLimiter(100, 50);

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