Created
September 6, 2012 13:07
-
-
Save davybrion/3656057 to your computer and use it in GitHub Desktop.
code snippets for "The Circuit Breaker" post
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class CircuitBreakerState | |
{ | |
protected readonly CircuitBreaker circuitBreaker; | |
protected CircuitBreakerState(CircuitBreaker circuitBreaker) | |
{ | |
this.circuitBreaker = circuitBreaker; | |
} | |
public virtual void ProtectedCodeIsAboutToBeCalled() { } | |
public virtual void ProtectedCodeHasBeenCalled() { } | |
public virtual void ActUponException(Exception e) { circuitBreaker.IncreaseFailureCount(); } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ClosedState : CircuitBreakerState | |
{ | |
public ClosedState(CircuitBreaker circuitBreaker) : base(circuitBreaker) | |
{ | |
circuitBreaker.ResetFailureCount(); | |
} | |
public override void ActUponException(Exception e) | |
{ | |
base.ActUponException(e); | |
if (circuitBreaker.ThresholdReached()) circuitBreaker.MoveToOpenState(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class OpenState : CircuitBreakerState | |
{ | |
private readonly Timer timer; | |
public OpenState(CircuitBreaker circuitBreaker) : base(circuitBreaker) | |
{ | |
timer = new Timer(circuitBreaker.Timeout.TotalMilliseconds); | |
timer.Elapsed += TimeoutHasBeenReached; | |
timer.AutoReset = false; | |
timer.Start(); | |
} | |
private void TimeoutHasBeenReached(object sender, ElapsedEventArgs e) | |
{ | |
circuitBreaker.MoveToHalfOpenState(); | |
} | |
public override void ProtectedCodeIsAboutToBeCalled() | |
{ | |
base.ProtectedCodeIsAboutToBeCalled(); | |
throw new OpenCircuitException(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class HalfOpenState : CircuitBreakerState | |
{ | |
public HalfOpenState(CircuitBreaker circuitBreaker) : base(circuitBreaker) {} | |
public override void ActUponException(Exception e) | |
{ | |
base.ActUponException(e); | |
circuitBreaker.MoveToOpenState(); | |
} | |
public override void ProtectedCodeHasBeenCalled() | |
{ | |
base.ProtectedCodeHasBeenCalled(); | |
circuitBreaker.MoveToClosedState(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CircuitBreaker | |
{ | |
private readonly object monitor = new object(); | |
private CircuitBreakerState state; | |
public CircuitBreaker(int threshold, TimeSpan timeout) | |
{ | |
if (threshold < 1) | |
{ | |
throw new ArgumentOutOfRangeException("threshold", "Threshold should be greater than 0"); | |
} | |
if (timeout.TotalMilliseconds < 1) | |
{ | |
throw new ArgumentOutOfRangeException("timeout", "Timeout should be greater than 0"); | |
} | |
Threshold = threshold; | |
Timeout = timeout; | |
MoveToClosedState(); | |
} | |
public int Failures { get; private set; } | |
public int Threshold { get; private set; } | |
public TimeSpan Timeout { get; private set; } | |
public bool IsClosed | |
{ | |
get { return state is ClosedState; } | |
} | |
public bool IsOpen | |
{ | |
get { return state is OpenState; } | |
} | |
public bool IsHalfOpen | |
{ | |
get { return state is HalfOpenState; } | |
} | |
internal void MoveToClosedState() | |
{ | |
state = new ClosedState(this); | |
} | |
internal void MoveToOpenState() | |
{ | |
state = new OpenState(this); | |
} | |
internal void MoveToHalfOpenState() | |
{ | |
state = new HalfOpenState(this); | |
} | |
internal void IncreaseFailureCount() | |
{ | |
Failures++; | |
} | |
internal void ResetFailureCount() | |
{ | |
Failures = 0; | |
} | |
public bool ThresholdReached() | |
{ | |
return Failures >= Threshold; | |
} | |
public void AttemptCall(Action protectedCode) | |
{ | |
using (TimedLock.Lock(monitor)) | |
{ | |
state.ProtectedCodeIsAboutToBeCalled(); | |
} | |
try | |
{ | |
protectedCode(); | |
} | |
catch (Exception e) | |
{ | |
using (TimedLock.Lock(monitor)) | |
{ | |
state.ActUponException(e); | |
} | |
throw; | |
} | |
using (TimedLock.Lock(monitor)) | |
{ | |
state.ProtectedCodeHasBeenCalled(); | |
} | |
} | |
public void Close() | |
{ | |
using (TimedLock.Lock(monitor)) | |
{ | |
MoveToClosedState(); | |
} | |
} | |
public void Open() | |
{ | |
using (TimedLock.Lock(monitor)) | |
{ | |
MoveToOpenState(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void ProcessOrder(OrderInfo orderInfo) | |
{ | |
var proxy = new OrderProcessorServiceProxy(); | |
_orderProcessoryCircuitBreaker.AttemptCall(() => proxy.ProcessOrder(orderInfo)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment