--- CircuitBreaker/src/dk/thoerup/curcuitbreaker/CircuitBreaker.java 2009/10/05 19:44:40 393 +++ miscJava/CircuitBreaker/src/main/java/dk/thoerup/circuitbreaker/CircuitBreaker.java 2015/06/09 09:28:14 2572 @@ -1,11 +1,23 @@ -package dk.thoerup.curcuitbreaker; +package dk.thoerup.circuitbreaker; -import java.util.logging.Logger; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import dk.thoerup.circuitbreaker.config.BreakerConfig; +import dk.thoerup.circuitbreaker.config.StaticConfig; +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 -/* example of how it can be used -protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + private CircuitBreaker cb = new CircuitBreaker("test", 5, 10000); + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { class TestInvocation implements CircuitInvocation { String url; public TestInvocation(String url) { @@ -27,7 +39,7 @@ try { String s = (String) cb.invoke(new TestInvocation("http://rafiki/test")); response.getWriter().print(s); - } catch (Throwable e) { + } catch (Exception e) { logger.warning( e.getMessage() ); response.sendError(500); return; @@ -38,29 +50,45 @@ public class CircuitBreaker{ - Logger logger = Logger.getLogger(CircuitBreaker.class.getName()); - - private CircuitBreakerState currentState; + private volatile CircuitBreakerState currentState; - private OpenState open = new OpenState(); - private HalfOpenState halfOpen = new HalfOpenState(); - private ClosedState closed = new ClosedState(); + private final OpenState open = new OpenState(); + private final HalfOpenState halfOpen = new HalfOpenState(); + private final ClosedState closed = new ClosedState(); private String name; - public CircuitBreaker(String name, int threshold, long timeoutMS) { - closed.setThreshold(threshold); - open.setTimeout(timeoutMS); + private ExecutorService executor = null; + private Notifier notifier = new NullNotifier(); + private Statistics stats = new NullStatistics(); + + @Deprecated + public CircuitBreaker(String name, int threshold, int timeoutMS) { + this(name, new StaticConfig(threshold, 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 Throwable + public Object invoke(CircuitInvocation invocation) throws Exception { + stats.addStatistics(Event.Invocation); + Object result = null; try { @@ -68,43 +96,141 @@ result = invocation.proceed(); getState().postInvoke(this); } - catch(Throwable t) - { - getState().onError(this, t); - throw t; + catch(Exception e) + { + if (e instanceof CircuitBreakerException) { + stats.addStatistics(Event.InvocationBlocked); + } else { + stats.addStatistics(Event.InvocationFailure); + } + + getState().onError(this, e); + throw e; } return result; } public void tripBreaker() { - synchronized(this) { - currentState = open; - open.trip(); - - logger.warning("Circuitbreaker tripBreaker - " + name); - } + 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(this, event); + stats.addStatistics(event); + } + } + } + public void attemptReset() { synchronized(this) { - currentState = halfOpen; - - logger.warning("Circuitbreaker attemptReset - " + name); + if (currentState != halfOpen) { // TODO:Is this conditional necessary ?? + currentState = halfOpen; + notifier.sendNotification(this, Event.BreakerAttemptReset); + stats.addStatistics(Event.BreakerAttemptReset); + } } + } public void reset() { synchronized(this) { - currentState = closed; - - logger.warning("Circuitbreaker reset - " + name); + if (currentState != closed) { // TODO: Is this conditional necessary ?? + 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) { return currentState; } } + + public boolean isClosed() { + return (getState() == closed); + } + + public boolean isOpen() { + return (getState() == open); + } + + public String getName() { + return name; + } + + public String getStateName() { + return getState().getName(); + } + + public int getThreshold() { + return closed.getThreshold(); + } + + public int getTimeout() { + return (int)open.getTimeout(); + } + + public int getFailureCount() { + if (getState() == closed) { + return closed.getFailureCount(); + } else { + return -1; + } + } + + public long getElapsed() { + if (getState() == open) { + return open.getElapsed(); + } else { + return -1; + } + } + + public void setNotifier(Notifier notifier) { + synchronized(this) { + this.notifier = notifier; + } + } + + public String getNotifierName() { + return NotiferHelper.getName(notifier); + } + + 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; + + } + }