{"id":13430460,"url":"https://github.com/App-vNext/Polly","last_synced_at":"2025-03-16T05:31:00.465Z","repository":{"id":8315881,"uuid":"9864166","full_name":"App-vNext/Polly","owner":"App-vNext","description":"Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. From version 6.0.1, Polly targets .NET Standard 1.1 and 2.0+.","archived":false,"fork":false,"pushed_at":"2025-03-14T20:11:33.000Z","size":45298,"stargazers_count":13652,"open_issues_count":13,"forks_count":1245,"subscribers_count":346,"default_branch":"main","last_synced_at":"2025-03-15T15:48:11.651Z","etag":null,"topics":["circuit-breaker","circuit-breaker-pattern","dotnet","fault-handler","resilience","resiliency-patterns","retry-strategies","transient-fault-handling"],"latest_commit_sha":null,"homepage":"https://www.thepollyproject.org","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/App-vNext.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["martincostello"]}},"created_at":"2013-05-05T04:40:04.000Z","updated_at":"2025-03-15T01:16:09.000Z","dependencies_parsed_at":"2023-11-10T07:05:19.844Z","dependency_job_id":"a7402c55-4a89-4ae4-afe8-61769a582917","html_url":"https://github.com/App-vNext/Polly","commit_stats":{"total_commits":2090,"total_committers":114,"mean_commits":"18.333333333333332","dds":0.8363636363636364,"last_synced_commit":"b0cc0acef589892ebdff201aecdafcb64c1af51c"},"previous_names":[],"tags_count":56,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/App-vNext%2FPolly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/App-vNext%2FPolly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/App-vNext%2FPolly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/App-vNext%2FPolly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/App-vNext","download_url":"https://codeload.github.com/App-vNext/Polly/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243754013,"owners_count":20342538,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["circuit-breaker","circuit-breaker-pattern","dotnet","fault-handler","resilience","resiliency-patterns","retry-strategies","transient-fault-handling"],"created_at":"2024-07-31T02:00:54.009Z","updated_at":"2025-03-16T05:30:55.447Z","avatar_url":"https://github.com/App-vNext.png","language":"C#","readme":"# Polly\n\nPolly is a .NET resilience and transient-fault-handling library that allows developers to express resilience strategies such as Retry, Circuit Breaker, Hedging, Timeout, Rate Limiter and Fallback in a fluent and thread-safe manner.\n\n[\u003cimg align=\"right\" src=\"https://github.com/dotnet/swag/raw/main/logo/dotnetfoundation_v4_small.png\" width=\"100\" alt=\"The .NET Foundation logo\" /\u003e](https://www.dotnetfoundation.org/)\nWe are a member of the [.NET Foundation](https://www.dotnetfoundation.org/about)!\n\n**Keep up to date with new feature announcements, tips \u0026 tricks, and other news through [www.thepollyproject.org](https://www.thepollyproject.org)**\n\n[![Build status](https://github.com/App-vNext/Polly/workflows/build/badge.svg?branch=main\u0026event=push)](https://github.com/App-vNext/Polly/actions?query=workflow%3Abuild+branch%3Amain+event%3Apush) [![Code coverage](https://codecov.io/gh/App-vNext/Polly/branch/main/graph/badge.svg)](https://codecov.io/gh/App-vNext/Polly) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/App-vNext/Polly/badge)](https://securityscorecards.dev/viewer/?uri=github.com/App-vNext/Polly)\n\n\u003c!-- markdownlint-disable MD042 --\u003e\n[![Polly logo](https://raw.github.com/App-vNext/Polly/main/Polly-Logo.png)](#)\n\u003c!-- markdownlint-enable MD034 --\u003e\n\n\u003e [!IMPORTANT]\n\u003e This documentation describes the new Polly v8 API. If you are using the v7 API, please refer to the [previous version](https://github.com/App-vNext/Polly/tree/7.2.4) of the documentation.\n\n## NuGet Packages\n\n| **Package** | **Latest Version** | **About** |\n|:--|:--|:--|\n| `Polly.Core` | [![NuGet](https://buildstats.info/nuget/Polly.Core)](https://www.nuget.org/packages/Polly.Core/ \"Download Polly.Core from NuGet.org\") | The core abstractions and [built-in strategies](https://www.pollydocs.org/strategies/index). |\n| `Polly.Extensions` | [![NuGet](https://buildstats.info/nuget/Polly.Extensions)](https://www.nuget.org/packages/Polly.Extensions/ \"Download Polly.Extensions from NuGet.org\") | [Telemetry](https://www.pollydocs.org/advanced/telemetry) and [dependency injection](https://www.pollydocs.org/advanced/dependency-injection) support. |\n| `Polly.RateLimiting` | [![NuGet](https://buildstats.info/nuget/Polly.RateLimiting)](https://www.nuget.org/packages/Polly.RateLimiting/ \"Download Polly.RateLimiting from NuGet.org\") | Integration with [`System.Threading.RateLimiting`](https://www.nuget.org/packages/System.Threading.RateLimiting) APIs. |\n| `Polly.Testing` | [![NuGet](https://buildstats.info/nuget/Polly.Testing)](https://www.nuget.org/packages/Polly.Testing/ \"Download Polly.Testing from NuGet.org\") | [Testing support](https://www.pollydocs.org/advanced/testing) for Polly libraries. |\n| `Polly` | [![NuGet](https://buildstats.info/nuget/Polly)](https://www.nuget.org/packages/Polly/ \"Download Polly from NuGet.org\") | This package contains the legacy API exposed by versions of the Polly library before version 8. |\n\n## Documentation\n\nThis README aims to give a quick overview of some Polly features - including enough to get you started with any resilience strategy. For deeper detail on any resilience strategy, and many other aspects of Polly, be sure also to check out [pollydocs.org][polly-docs].\n\n## Quick start\n\nTo use Polly, you must provide a callback and execute it using [**resilience pipeline**](https://www.pollydocs.org/pipelines). A resilience pipeline is a combination of one or more [**resilience strategies**](https://www.pollydocs.org/strategies) such as retry, timeout, and rate limiter. Polly uses **builders** to integrate these strategies into a pipeline.\n\nTo get started, first add the [Polly.Core](https://www.nuget.org/packages/Polly.Core/) package to your project by running the following command:\n\n```sh\ndotnet add package Polly.Core\n```\n\nYou can create a `ResiliencePipeline` using the `ResiliencePipelineBuilder` class as shown below:\n\n\u003c!-- snippet: quick-start --\u003e\n```cs\n// Create an instance of builder that exposes various extensions for adding resilience strategies\nResiliencePipeline pipeline = new ResiliencePipelineBuilder()\n    .AddRetry(new RetryStrategyOptions()) // Add retry using the default options\n    .AddTimeout(TimeSpan.FromSeconds(10)) // Add 10 seconds timeout\n    .Build(); // Builds the resilience pipeline\n\n// Execute the pipeline asynchronously\nawait pipeline.ExecuteAsync(static async token =\u003e { /* Your custom logic goes here */ }, cancellationToken);\n```\n\u003c!-- endSnippet --\u003e\n\n### Dependency injection\n\nIf you prefer to define resilience pipelines using [`IServiceCollection`](https://learn.microsoft.com/dotnet/api/microsoft.extensions.dependencyinjection.iservicecollection), you'll need to install the [Polly.Extensions](https://www.nuget.org/packages/Polly.Extensions/) package:\n\n```sh\ndotnet add package Polly.Extensions\n```\n\nYou can then define your resilience pipeline using the `AddResiliencePipeline(...)` extension method as shown:\n\n\u003c!-- snippet: quick-start-di --\u003e\n```cs\nvar services = new ServiceCollection();\n\n// Define a resilience pipeline with the name \"my-pipeline\"\nservices.AddResiliencePipeline(\"my-pipeline\", builder =\u003e\n{\n    builder\n        .AddRetry(new RetryStrategyOptions())\n        .AddTimeout(TimeSpan.FromSeconds(10));\n});\n\n// Build the service provider\nvar serviceProvider = services.BuildServiceProvider();\n\n// Retrieve a ResiliencePipelineProvider that dynamically creates and caches the resilience pipelines\nvar pipelineProvider = serviceProvider.GetRequiredService\u003cResiliencePipelineProvider\u003cstring\u003e\u003e();\n\n// Retrieve your resilience pipeline using the name it was registered with\nResiliencePipeline pipeline = pipelineProvider.GetPipeline(\"my-pipeline\");\n\n// Alternatively, you can use keyed services to retrieve the resilience pipeline\npipeline = serviceProvider.GetRequiredKeyedService\u003cResiliencePipeline\u003e(\"my-pipeline\");\n\n// Execute the pipeline\nawait pipeline.ExecuteAsync(static async token =\u003e\n{\n    // Your custom logic goes here\n});\n```\n\u003c!-- endSnippet --\u003e\n\n## Resilience strategies\n\nPolly provides a variety of resilience strategies. Alongside the comprehensive guides for each strategy, the wiki also includes an [overview of the role each strategy plays in resilience engineering](https://github.com/App-vNext/Polly/wiki/Transient-fault-handling-and-proactive-resilience-engineering).\n\nPolly categorizes resilience strategies into two main groups:\n\n### Reactive\n\nThese strategies handle specific exceptions that are thrown, or results that are returned, by the callbacks executed through the strategy.\n\n| Strategy | Premise | AKA | Mitigation |\n| ------------- | ------------- | -------------- | ------------ |\n| [**Retry** family](#retry) | Many faults are transient and may self-correct after a short delay. | *Maybe it's just a blip* | Allows configuring automatic retries. |\n| [**Circuit-breaker** family](#circuit-breaker) | When a system is seriously struggling, failing fast is better than making users/callers wait. \u003cbr/\u003e\u003cbr/\u003eProtecting a faulting system from overload can help it recover. | *Stop doing it if it hurts* \u003cbr/\u003e\u003cbr/\u003e*Give that system a break* | Breaks the circuit (blocks executions) for a period, when faults exceed some pre-configured threshold. |\n| [**Fallback**](#fallback) | Things will still fail - plan what you will do when that happens. | *Degrade gracefully* | Defines an alternative value to be returned (or action to be executed) on failure. |\n| [**Hedging**](#hedging) | Things can be slow sometimes, plan what you will do when that happens. | *Hedge your bets* | Executes parallel actions when things are slow and waits for the fastest one. |\n\n### Proactive\n\nUnlike reactive strategies, proactive strategies do not focus on handling errors, but the callbacks might throw or return.\nThey can make proactive decisions to cancel or reject the execution of callbacks.\n\n| Strategy | Premise | AKA | Prevention |\n| ----------- | ------------- | -------------- | ------------ |\n| [**Timeout**](#timeout) | Beyond a certain wait, a success result is unlikely. | *Don't wait forever* | Guarantees the caller won't have to wait beyond the timeout. |\n| [**Rate Limiter**](#rate-limiter) | Limiting the rate a system handles requests is another way to control load. \u003cbr/\u003e \u003cbr/\u003e This can apply to the way your system accepts incoming calls, and/or to the way you call downstream services. | *Slow down a bit, will you?* | Constrains executions to not exceed a certain rate. |\n\nVisit [resilience strategies](https://www.pollydocs.org/strategies) docs to explore how to configure individual resilience strategies in more detail.\n\n### Retry\n\n\u003c!-- snippet: retry --\u003e\n```cs\n// Retry using the default options.\n// See https://www.pollydocs.org/strategies/retry#defaults for defaults.\nvar optionsDefaults = new RetryStrategyOptions();\n\n// For instant retries with no delay\nvar optionsNoDelay = new RetryStrategyOptions\n{\n    Delay = TimeSpan.Zero\n};\n\n// For advanced control over the retry behavior, including the number of attempts,\n// delay between retries, and the types of exceptions to handle.\nvar optionsComplex = new RetryStrategyOptions\n{\n    ShouldHandle = new PredicateBuilder().Handle\u003cSomeExceptionType\u003e(),\n    BackoffType = DelayBackoffType.Exponential,\n    UseJitter = true,  // Adds a random factor to the delay\n    MaxRetryAttempts = 4,\n    Delay = TimeSpan.FromSeconds(3),\n};\n\n// To use a custom function to generate the delay for retries\nvar optionsDelayGenerator = new RetryStrategyOptions\n{\n    MaxRetryAttempts = 2,\n    DelayGenerator = static args =\u003e\n    {\n        var delay = args.AttemptNumber switch\n        {\n            0 =\u003e TimeSpan.Zero,\n            1 =\u003e TimeSpan.FromSeconds(1),\n            _ =\u003e TimeSpan.FromSeconds(5)\n        };\n\n        // This example uses a synchronous delay generator,\n        // but the API also supports asynchronous implementations.\n        return new ValueTask\u003cTimeSpan?\u003e(delay);\n    }\n};\n\n// To extract the delay from the result object\nvar optionsExtractDelay = new RetryStrategyOptions\u003cHttpResponseMessage\u003e\n{\n    DelayGenerator = static args =\u003e\n    {\n        if (args.Outcome.Result is HttpResponseMessage responseMessage \u0026\u0026\n            TryGetDelay(responseMessage, out TimeSpan delay))\n        {\n            return new ValueTask\u003cTimeSpan?\u003e(delay);\n        }\n\n        // Returning null means the retry strategy will use its internal delay for this attempt.\n        return new ValueTask\u003cTimeSpan?\u003e((TimeSpan?)null);\n    }\n};\n\n// To get notifications when a retry is performed\nvar optionsOnRetry = new RetryStrategyOptions\n{\n    MaxRetryAttempts = 2,\n    OnRetry = static args =\u003e\n    {\n        Console.WriteLine(\"OnRetry, Attempt: {0}\", args.AttemptNumber);\n\n        // Event handlers can be asynchronous; here, we return an empty ValueTask.\n        return default;\n    }\n};\n\n// To keep retrying indefinitely or until success use int.MaxValue.\nvar optionsIndefiniteRetry = new RetryStrategyOptions\n{\n    MaxRetryAttempts = int.MaxValue,\n};\n\n// Add a retry strategy with a RetryStrategyOptions{\u003cTResult\u003e} instance to the pipeline\nnew ResiliencePipelineBuilder().AddRetry(optionsDefaults);\nnew ResiliencePipelineBuilder\u003cHttpResponseMessage\u003e().AddRetry(optionsExtractDelay);\n```\n\u003c!-- endSnippet --\u003e\n\nIf all retries fail, a retry strategy rethrows the final exception back to the calling code.\n\nFor more details, visit the [retry strategy](https://www.pollydocs.org/strategies/retry) documentation.\n\n### Circuit Breaker\n\n\u003c!-- snippet: circuit-breaker --\u003e\n```cs\n// Circuit breaker with default options.\n// See https://www.pollydocs.org/strategies/circuit-breaker#defaults for defaults.\nvar optionsDefaults = new CircuitBreakerStrategyOptions();\n\n// Circuit breaker with customized options:\n// The circuit will break if more than 50% of actions result in handled exceptions,\n// within any 10-second sampling duration, and at least 8 actions are processed.\nvar optionsComplex = new CircuitBreakerStrategyOptions\n{\n    FailureRatio = 0.5,\n    SamplingDuration = TimeSpan.FromSeconds(10),\n    MinimumThroughput = 8,\n    BreakDuration = TimeSpan.FromSeconds(30),\n    ShouldHandle = new PredicateBuilder().Handle\u003cSomeExceptionType\u003e()\n};\n\n// Circuit breaker using BreakDurationGenerator:\n// The break duration is dynamically determined based on the properties of BreakDurationGeneratorArguments.\nvar optionsBreakDurationGenerator = new CircuitBreakerStrategyOptions\n{\n    FailureRatio = 0.5,\n    SamplingDuration = TimeSpan.FromSeconds(10),\n    MinimumThroughput = 8,\n    BreakDurationGenerator = static args =\u003e new ValueTask\u003cTimeSpan\u003e(TimeSpan.FromMinutes(args.FailureCount)),\n};\n\n// Handle specific failed results for HttpResponseMessage:\nvar optionsShouldHandle = new CircuitBreakerStrategyOptions\u003cHttpResponseMessage\u003e\n{\n    ShouldHandle = new PredicateBuilder\u003cHttpResponseMessage\u003e()\n        .Handle\u003cSomeExceptionType\u003e()\n        .HandleResult(response =\u003e response.StatusCode == HttpStatusCode.InternalServerError)\n};\n\n// Monitor the circuit state, useful for health reporting:\nvar stateProvider = new CircuitBreakerStateProvider();\nvar optionsStateProvider = new CircuitBreakerStrategyOptions\u003cHttpResponseMessage\u003e\n{\n    StateProvider = stateProvider\n};\n\nvar circuitState = stateProvider.CircuitState;\n\n/*\nCircuitState.Closed - Normal operation; actions are executed.\nCircuitState.Open - Circuit is open; actions are blocked.\nCircuitState.HalfOpen - Recovery state after break duration expires; actions are permitted.\nCircuitState.Isolated - Circuit is manually held open; actions are blocked.\n*/\n\n// Manually control the Circuit Breaker state:\nvar manualControl = new CircuitBreakerManualControl();\nvar optionsManualControl = new CircuitBreakerStrategyOptions\n{\n    ManualControl = manualControl\n};\n\n// Manually isolate a circuit, e.g., to isolate a downstream service.\nawait manualControl.IsolateAsync();\n\n// Manually close the circuit to allow actions to be executed again.\nawait manualControl.CloseAsync();\n\n// Add a circuit breaker strategy with a CircuitBreakerStrategyOptions{\u003cTResult\u003e} instance to the pipeline\nnew ResiliencePipelineBuilder().AddCircuitBreaker(optionsDefaults);\nnew ResiliencePipelineBuilder\u003cHttpResponseMessage\u003e().AddCircuitBreaker(optionsStateProvider);\n```\n\u003c!-- endSnippet --\u003e\n\nFor more details, visit the [circuit breaker strategy](https://www.pollydocs.org/strategies/circuit-breaker) documentation.\n\n### Fallback\n\n\u003c!-- snippet: fallback --\u003e\n```cs\n// A fallback/substitute value if an operation fails.\nvar optionsSubstitute = new FallbackStrategyOptions\u003cUserAvatar\u003e\n{\n    ShouldHandle = new PredicateBuilder\u003cUserAvatar\u003e()\n        .Handle\u003cSomeExceptionType\u003e()\n        .HandleResult(r =\u003e r is null),\n    FallbackAction = static args =\u003e Outcome.FromResultAsValueTask(UserAvatar.Blank)\n};\n\n// Use a dynamically generated value if an operation fails.\nvar optionsFallbackAction = new FallbackStrategyOptions\u003cUserAvatar\u003e\n{\n    ShouldHandle = new PredicateBuilder\u003cUserAvatar\u003e()\n        .Handle\u003cSomeExceptionType\u003e()\n        .HandleResult(r =\u003e r is null),\n    FallbackAction = static args =\u003e\n    {\n        var avatar = UserAvatar.GetRandomAvatar();\n        return Outcome.FromResultAsValueTask(avatar);\n    }\n};\n\n// Use a default or dynamically generated value, and execute an additional action if the fallback is triggered.\nvar optionsOnFallback = new FallbackStrategyOptions\u003cUserAvatar\u003e\n{\n    ShouldHandle = new PredicateBuilder\u003cUserAvatar\u003e()\n        .Handle\u003cSomeExceptionType\u003e()\n        .HandleResult(r =\u003e r is null),\n    FallbackAction = static args =\u003e\n    {\n        var avatar = UserAvatar.GetRandomAvatar();\n        return Outcome.FromResultAsValueTask(UserAvatar.Blank);\n    },\n    OnFallback = static args =\u003e\n    {\n        // Add extra logic to be executed when the fallback is triggered, such as logging.\n        return default; // Returns an empty ValueTask\n    }\n};\n\n// Add a fallback strategy with a FallbackStrategyOptions\u003cTResult\u003e instance to the pipeline\nnew ResiliencePipelineBuilder\u003cUserAvatar\u003e().AddFallback(optionsOnFallback);\n```\n\u003c!-- endSnippet --\u003e\n\nFor more details, visit the [fallback strategy](https://www.pollydocs.org/strategies/fallback) documentation.\n\n### Hedging\n\n\u003c!-- snippet: hedging --\u003e\n```cs\n// Hedging with default options.\n// See https://www.pollydocs.org/strategies/hedging#defaults for defaults.\nvar optionsDefaults = new HedgingStrategyOptions\u003cHttpResponseMessage\u003e();\n\n// A customized hedging strategy that retries up to 3 times if the execution\n// takes longer than 1 second or if it fails due to an exception or returns an HTTP 500 Internal Server Error.\nvar optionsComplex = new HedgingStrategyOptions\u003cHttpResponseMessage\u003e\n{\n    ShouldHandle = new PredicateBuilder\u003cHttpResponseMessage\u003e()\n        .Handle\u003cSomeExceptionType\u003e()\n        .HandleResult(response =\u003e response.StatusCode == HttpStatusCode.InternalServerError),\n    MaxHedgedAttempts = 3,\n    Delay = TimeSpan.FromSeconds(1),\n    ActionGenerator = static args =\u003e\n    {\n        Console.WriteLine(\"Preparing to execute hedged action.\");\n\n        // Return a delegate function to invoke the original action with the action context.\n        // Optionally, you can also create a completely new action to be executed.\n        return () =\u003e args.Callback(args.ActionContext);\n    }\n};\n\n// Subscribe to hedging events.\nvar optionsOnHedging = new HedgingStrategyOptions\u003cHttpResponseMessage\u003e\n{\n    OnHedging = static args =\u003e\n    {\n        Console.WriteLine($\"OnHedging: Attempt number {args.AttemptNumber}\");\n        return default;\n    }\n};\n\n// Add a hedging strategy with a HedgingStrategyOptions\u003cTResult\u003e instance to the pipeline\nnew ResiliencePipelineBuilder\u003cHttpResponseMessage\u003e().AddHedging(optionsDefaults);\n```\n\u003c!-- endSnippet --\u003e\n\nIf all hedged attempts fail, the hedging strategy will either re-throw the original exception or return the original failed result to the caller.\n\nFor more details, visit the [hedging strategy](https://www.pollydocs.org/strategies/hedging) documentation.\n\n### Timeout\n\nThe timeout resilience strategy assumes delegates you execute support [co-operative cancellation](https://learn.microsoft.com/dotnet/standard/threading/cancellation-in-managed-threads). You must use `Execute/Async(...)` overloads taking a `CancellationToken`, and the executed delegate must honor that `CancellationToken`.\n\n\u003c!-- snippet: timeout --\u003e\n```cs\n// To add a timeout with a custom TimeSpan duration\nnew ResiliencePipelineBuilder().AddTimeout(TimeSpan.FromSeconds(3));\n\n// Timeout using the default options.\n// See https://www.pollydocs.org/strategies/timeout#defaults for defaults.\nvar optionsDefaults = new TimeoutStrategyOptions();\n\n// To add a timeout using a custom timeout generator function\nvar optionsTimeoutGenerator = new TimeoutStrategyOptions\n{\n    TimeoutGenerator = static args =\u003e\n    {\n        // Note: the timeout generator supports asynchronous operations\n        return new ValueTask\u003cTimeSpan\u003e(TimeSpan.FromSeconds(123));\n    }\n};\n\n// To add a timeout and listen for timeout events\nvar optionsOnTimeout = new TimeoutStrategyOptions\n{\n    TimeoutGenerator = static args =\u003e\n    {\n        // Note: the timeout generator supports asynchronous operations\n        return new ValueTask\u003cTimeSpan\u003e(TimeSpan.FromSeconds(123));\n    },\n    OnTimeout = static args =\u003e\n    {\n        Console.WriteLine($\"{args.Context.OperationKey}: Execution timed out after {args.Timeout.TotalSeconds} seconds.\");\n        return default;\n    }\n};\n\n// Add a timeout strategy with a TimeoutStrategyOptions instance to the pipeline\nnew ResiliencePipelineBuilder().AddTimeout(optionsDefaults);\n```\n\u003c!-- endSnippet --\u003e\n\nTimeout strategies throw `TimeoutRejectedException` when a timeout occurs.\n\nFor more details, visit the [timeout strategy](https://www.pollydocs.org/strategies/timeout) documentation.\n\n### Rate Limiter\n\n\u003c!-- snippet: rate-limiter --\u003e\n```cs\n// Add rate limiter with default options.\n// See https://www.pollydocs.org/strategies/rate-limiter#defaults for defaults.\nnew ResiliencePipelineBuilder()\n    .AddRateLimiter(new RateLimiterStrategyOptions());\n\n// Create a rate limiter to allow a maximum of 100 concurrent executions and a queue of 50.\nnew ResiliencePipelineBuilder()\n    .AddConcurrencyLimiter(100, 50);\n\n// Create a rate limiter that allows 100 executions per minute.\nnew ResiliencePipelineBuilder()\n    .AddRateLimiter(new SlidingWindowRateLimiter(\n        new SlidingWindowRateLimiterOptions\n        {\n            PermitLimit = 100,\n            Window = TimeSpan.FromMinutes(1)\n        }));\n```\n\u003c!-- endSnippet --\u003e\n\nRate limiter strategy throws `RateLimiterRejectedException` if execution is rejected.\n\nFor more details, visit the [rate limiter strategy](https://www.pollydocs.org/strategies/rate-limiter) documentation.\n\n## Chaos engineering\n\nStarting with version `8.3.0`, Polly has integrated [Simmy](https://github.com/Polly-Contrib/Simmy), a chaos engineering library, directly into its core. For more information, please refer to the dedicated [chaos engineering documentation](https://www.pollydocs.org/chaos/).\n\n## Next steps\n\nTo learn more about Polly, visit [pollydocs.org][polly-docs].\n\n## Samples\n\n- [Samples](samples/README.md): Samples in this repository that serve as an introduction to Polly.\n- [Polly-Samples](https://github.com/App-vNext/Polly-Samples): Contains practical examples for using various implementations of Polly. Please feel free to contribute to the Polly-Samples repository in order to assist others who are either learning Polly for the first time, or are seeking advanced examples and novel approaches provided by our generous community.\n- Microsoft's [eShopOnContainers project](https://github.com/dotnet/eShop): Sample project demonstrating a .NET Micro-services architecture and using Polly for resilience.\n\n## Sponsors\n\nThanks to the following companies for sponsoring the ongoing development of Polly.\n\n- [.NET on AWS Open Source Software Fund](https://github.com/aws/dotnet-foss)\n- [Microsoft's Free and Open Source Software Fund](https://github.com/microsoft/foss-fund)\n\n\u003c!-- markdownlint-disable MD042 --\u003e\n[![AWS logo](./logos/aws.png)](#)\n[![Microsoft logo](./logos/microsoft.png)](#)\n\u003c!-- markdownlint-enable MD034 --\u003e\n\nHelp support this project by becoming a sponsor through [GitHub Sponsors](https://github.com/sponsors/martincostello).\n\n## License\n\nLicensed under the terms of the [New BSD License](https://opensource.org/license/bsd-3-clause/)\n\n[polly-docs]: https://www.pollydocs.org/\n","funding_links":["https://github.com/sponsors/martincostello"],"categories":["Frameworks, Libraries and Tools","dotnet","C# #","Resilience and Fault Handling","C#","Tools","General","Resilience",".NET Learning Resources","🗒️ Cheatsheets","Misc","框架, 库和工具","C\\#",".NET Tools and Frameworks","杂项","6. Http Resiliency","EF Core Providers Connectors"],"sub_categories":["Distributed Computing","Objective-C Tools, Libraries, and Frameworks","Misc","Interfaces","📦 Libraries","分布式计算","Mesh networks","GUI - other","More information:"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FApp-vNext%2FPolly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FApp-vNext%2FPolly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FApp-vNext%2FPolly/lists"}