How to get it
Source code: hg.tath.am/reliability-patterns
What it solves
In our homes, we use circuit breakers to quickly isolate an electrical circuit when there’s a known fault.
Michael T. Nygard introduces this concept as a programming pattern in his book Release It!: Design and Deploy Production-Ready Software.
The essence of the pattern is that when one of your dependencies stops responding, you need to stop calling it for a little while. A file system that has exhausted its operation queue is not going to recover while you keep hammering it with new requests. A remote web service is not going to come back any faster if you keep opening new TCP connections and mindlessly waiting for the 30 second timeout. Worse yet, if your application normally expects that web service to respond in 100ms, suddenly starting to block for 30s is likely to deteriorate the performance of your own application and trigger a cascading failure.
Electrical circuit breakers ‘trip’ when a high current condition occurs. They then need to be manually ‘reset’ to close the circuit again.
Our programmatic circuit breaker will trip after an operation has more consecutive failures than a predetermined threshold. While the circuit breaker is open, operations will fail immediately without even attempting to be executed. After a reset timeout has elapsed, the circuit breaker will enter a half-open state. In this state, only the next call will be allowed to execute. If it fails, the circuit breaker will go straight back to the open state and the reset timer will be restarted. Once the service has recovered, calls will start flowing normally again.
Writing all this extra management code would be painful. This library manages it for you instead.
How to use it
Taking advantage of the library is as simple as wrapping your outgoing service call with
// Note: you'll need to keep this instance around var breaker = new CircuitBreaker(); var client = new SmtpClient(); var message = new MailMessage(); breaker.Execute(() => client.SendEmail(message));
The only caveat is that you need to manage the lifetime of the circuit breaker(s). You should create one instance for each distinct dependency, then keep this instance around for the life of your application. Do not create different instances for different operations that occur on the same system.
(Managing multiple circuit breakers via a container can be a bit tricky. I’ve published a separate example for how to do it with Autofac.)
It’s generally safe to add this pattern to existing code because it will only throw an exception in a scenario where your existing code would anyway.
You can also take advantage of built-in retry logic:
breaker.ExecuteWithRetries(() => client.SendEmail(message), 10, TimeSpan.FromSeconds(20));
Why is the package named ReliabilityPatterns instead of CircuitBreaker?
Because I hope to add more useful patterns in the future.