--- CircuitBreaker/src/dk/thoerup/curcuitbreaker/CircuitBreaker.java 2009/10/20 10:47:36 452 +++ miscJava/CircuitBreaker/src/main/java/dk/thoerup/circuitbreaker/CircuitBreaker.java 2017/12/28 09:34:47 3212 @@ -1,21 +1,28 @@ -package dk.thoerup.curcuitbreaker; +package dk.thoerup.circuitbreaker; -import dk.thoerup.curcuitbreaker.notification.Notifier; -import dk.thoerup.curcuitbreaker.notification.NullNotifier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import dk.thoerup.circuitbreaker.config.BreakerConfig; +import dk.thoerup.circuitbreaker.notification.NotiferHelper; +import dk.thoerup.circuitbreaker.notification.Notifier; +import dk.thoerup.circuitbreaker.notification.NullNotifier; +import dk.thoerup.circuitbreaker.statistics.NullStatistics; +import dk.thoerup.circuitbreaker.statistics.Statistics; /* Simple CircuitBreaker implementation - snipped from http://www.jroller.com/kenwdelong/entry/circuit_breaker_in_java * * example of how it can be used - private CircuitBreaker cb = new CircuitBreaker("test", 5, 10000); + private CircuitBreaker cb = new CircuitBreaker<>("test", 5, 10000); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - class TestInvocation implements CircuitInvocation { + class TestInvocation implements CircuitInvocation { String url; public TestInvocation(String url) { this.url = url; } - public Object proceed() throws Exception{ + public String proceed() throws Exception{ URL u = new URL(url); URLConnection c = u.openConnection(); @@ -29,7 +36,7 @@ } try { - String s = (String) cb.invoke(new TestInvocation("http://rafiki/test")); + String s = cb.invoke(new TestInvocation("http://rafiki/test")); response.getWriter().print(s); } catch (Exception e) { logger.warning( e.getMessage() ); @@ -41,7 +48,7 @@ */ -public class CircuitBreaker{ +public class CircuitBreaker{ private volatile CircuitBreakerState currentState; @@ -51,21 +58,33 @@ private String name; + private ExecutorService executor = null; private Notifier notifier = new NullNotifier(); + private Statistics stats = new NullStatistics(); + - public CircuitBreaker(String name, int threshold, long timeoutMS) { - closed.setThreshold(threshold); - open.setTimeout(timeoutMS); + public CircuitBreaker(String name, BreakerConfig config) { + closed.setThreshold(config); + open.setTimeout(config); this.name = name; - - reset(); + + //set correct intial state + internalReset(); } + public synchronized void shutdown() { + if (executor != null) { + executor.shutdown(); + } + } - public Object invoke(CircuitInvocation invocation) throws Exception + + public T invoke(CircuitInvocation invocation) throws Exception { - Object result = null; + stats.addStatistics(Event.Invocation); + + T result = null; try { getState().preInvoke(this); @@ -73,7 +92,13 @@ getState().postInvoke(this); } catch(Exception e) - { + { + if (e instanceof CircuitBreakerException) { + stats.addStatistics(Event.InvocationBlocked); + } else { + stats.addStatistics(Event.InvocationFailure); + } + getState().onError(this, e); throw e; } @@ -81,21 +106,32 @@ } public void tripBreaker() { - synchronized(this) { + commonTripBreaker(Event.BreakerTripped); + } + + //a re-trip should basically do the same as a normal trip, but it is here just to differentiate the two different events + public void retripBreaker() { + commonTripBreaker(Event.BreakerRetripped); + } + + private void commonTripBreaker(Event event) { + synchronized(this) { if (currentState != open) { // TODO:Is this conditional necessary ?? open.trip(); currentState = open; - notifier.sendNotification(name, Notifier.Event.BreakerTripped); + notifier.sendNotification(this, event); + stats.addStatistics(event); } - } + } } - + public void attemptReset() { synchronized(this) { if (currentState != halfOpen) { // TODO:Is this conditional necessary ?? currentState = halfOpen; - notifier.sendNotification(name, Notifier.Event.BreakerAttemptReset); + notifier.sendNotification(this, Event.BreakerAttemptReset); + stats.addStatistics(Event.BreakerAttemptReset); } } @@ -104,12 +140,19 @@ public void reset() { synchronized(this) { if (currentState != closed) { // TODO: Is this conditional necessary ?? - currentState = closed; - notifier.sendNotification(name, Notifier.Event.BreakerReset); + internalReset(); + notifier.sendNotification(this, Event.BreakerReset); + stats.addStatistics(Event.BreakerReset); } } } + //This one actually sets the correct closed/reset state + private void internalReset() { + closed.resetFailureCount(); + currentState = closed; + } + private CircuitBreakerState getState() { synchronized(this) { @@ -158,11 +201,31 @@ } public void setNotifier(Notifier notifier) { - this.notifier = notifier; + synchronized(this) { + this.notifier = notifier; + } + } + + public String getNotifierName() { + return NotiferHelper.getName(notifier); } - public String getNotifierName() { - return notifier.getClass().getName(); + public void setStatistics(Statistics newStats) { + this.stats = newStats; + } + + public Statistics getStatistics() { + return this.stats; + } + + public synchronized ExecutorService getExecutor() { + + if (executor == null) { + executor = Executors.newFixedThreadPool(1); + } + + return executor; + } }