{"id":17224825,"url":"https://github.com/pseudomuto/resilient.net","last_synced_at":"2025-10-13T16:30:48.200Z","repository":{"id":144186987,"uuid":"50485445","full_name":"pseudomuto/Resilient.Net","owner":"pseudomuto","description":"A library to help make applications more resilient to failure","archived":false,"fork":false,"pushed_at":"2016-05-06T01:37:42.000Z","size":203,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-06T13:46:49.618Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pseudomuto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-01-27T06:00:35.000Z","updated_at":"2018-04-19T08:37:33.000Z","dependencies_parsed_at":"2024-06-17T13:15:20.510Z","dependency_job_id":null,"html_url":"https://github.com/pseudomuto/Resilient.Net","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseudomuto%2FResilient.Net","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseudomuto%2FResilient.Net/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseudomuto%2FResilient.Net/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pseudomuto%2FResilient.Net/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pseudomuto","download_url":"https://codeload.github.com/pseudomuto/Resilient.Net/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236369113,"owners_count":19138053,"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":[],"created_at":"2024-10-15T04:12:04.766Z","updated_at":"2025-10-13T16:30:42.917Z","avatar_url":"https://github.com/pseudomuto.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Resilient.Net\n\n[![Build Status](https://travis-ci.org/pseudomuto/Resilient.Net.svg?branch=master)](https://travis-ci.org/pseudomuto/Resilient.Net)\n[![NuGet](https://img.shields.io/nuget/dt/resilient.net.svg)](https://www.nuget.org/packages/resilient.net/)\n\nA library to help make applications more resilient to failures.\n\n## Installation\n\nResilient.Net is available on NuGet.\n\n```\nInstall-Package resilient.net\n```\n\n[Circuit Breaker Pattern]: https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern\n\n## Circuit Breaker\n\nThe [Circuit Breaker Pattern] combines the goals of failing fast with timeouts.\n\nThe basic idea is that if a timeout (or other exception) occurs for a given resource, it's likely to happen again for\nsome amount of time. Instead of constantly hitting the timeout, which ties up all your threads, the resource is marked\nas unavailable for some amount of time.  While unavailable, calls immediately trigger an exception.\n\n![Circuit Breaker](circuitbreaker.png)\n\n### Circuit Breaker States\n\nA circuit breaker can be in one of three states at any point in time. Transitioning from state to state is managed\nautomatically, however you can force a state using the `Force` method if necessary.\n\n_**Closed**_\n\nThe call is made. If an exception is thrown, the error count is incremented. Once the threshold is reached the circuit\nis opened.\n\n_**Open**_\n\nCalling `Execute` will immediately trigger an `OpenCircuitBreakerException` without attempting to call/query the\nexternal resource.\n\nAfter the `ResetTimeout` has lapsed, the circuit is moved to the half-open state.\n\n_**Half Open**_\n\nCalls are allowed through (one at a time) until the success threshold is reached, which will close the circuit. If an\nexception occurs at any point, the circuit is opened again.\n\n\u003e **NOTE:** State is local to an instance of `CircuitBreaker`. However, all methods are thread-safe, which means it is\ncompletely safe to keep a static instance around to share within your process.\n\n### Monitoring\n\nCircuit breaker state transitions are traced. To monitor the state of a breaker, you just need to [register a\n`TraceListener`](https://msdn.microsoft.com/en-us/library/sk36c28t(v=vs.110).aspx) and do what you will with the log.\n\n### Circuit Breaker Options\n\n| Property | Description | Default |\n|----------|-------------|---------|\n| ErrorThreshold | The number of errors that must occur before opening the circuit | `2` |\n| SuccessThreshold | The number of successful calls before the circuit is closed again | `2` |\n| InvocationTimout | The amount of time to attempt the call/query | `1s` |\n| ResetTimeout | The amount of time until trying the call/query again | `10s`\n\n### Usage\n\n```csharp\nvar options = new CircuitBreakerOptions {\n    ErrorThreshold = 2,\n    SuccessThreshold = 2,\n    InvocationTimeout = TimeSpan.FromSeconds(1),\n    ResetTimeout = TimeSpan.FromSeconds(10)\n};\n\nusing(var breaker = new CircuitBreaker(TaskScheduler.Default, options))\n{\n    try\n    {\n        return breaker.Execute(() =\u003e\n        {\n            // do something volatile...\n            return \"the result\";\n        });\n    }\n    catch(CircuitBreakerTimeoutException)\n    {\n      // fallback\n    }\n    catch(OpenCircuitBreakerException)\n    {\n      // fallback\n    }\n    catch(OTHER_EXCEPTIONS_YOU_CAN_HANDLE)\n    {\n      // fallback\n    }\n}\n```\n\nHaving code like this sprinkled throughout your code base is kind of a bad thing. IMO, it's far better to wrap this\ncode in a primitive you can use instead.\n\n#### For Example\n\n```csharp\nclass JSONFetcher : IDisposable\n{\n    private readonly CircuitBreaker _breaker;\n\n    public JSONFetcher()\n    {\n        // using default options and scheduler here...\n        _breaker = new CircuitBreaker();\n    }\n\n    public string FetchString(url)\n    {\n        // validate url first...\n\n        try\n        {\n            return _breaker.Execute(() =\u003e\n            {\n                using(var client = new WebClient())\n                {\n                    return client.DownloadString(url);\n                }\n            });\n        }\n        catch(CircuitBreakerTimeoutException)\n        {\n        }\n        catch(OpenCircuitBreakerException)\n        {\n        }\n        catch(WebException)\n        {\n        }\n\n        return null;\n    }\n\n    public void Dispose()\n    {\n        Dispose(true)\n        GC.SupressFinalize(this);\n    }\n\n    protected virtual void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _breaker.Dispose();\n        }\n    }\n}\n```\n\nThen this class can be used anywhere you fetch JSON strings like this:\n\n```csharp\npublic class PostAPI\n{\n    private static readonly string s_host = \"http://jsonplaceholder.typicode.com\";\n    private static readonly JSONFetcher s_fetcher = new JSONFetcher();\n\n    public Post GetPost(ulong id)\n    {\n        var json = s_fetcher.FetchString(string.concat(s_host, \"/posts/\", id));\n        if (json == null)\n        {\n            return null;\n        }\n\n        // convert to your model...\n        return model;\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpseudomuto%2Fresilient.net","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpseudomuto%2Fresilient.net","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpseudomuto%2Fresilient.net/lists"}