The Circuit Breakr Pattern aims to open the "circuit" after hitting a configurable threshold of erroneous method calls.

A natural fit is the use of an interceptor to measure the performance and monitor the exceptions. After reaching the threshold the interceptor returns without calling the target:

public class Breakr { private long errorCounter; private static final int FAILURES_COUNT = 5; private static final int TIMEOUT_IN_MS = 1000; @AroundInvoke public Object guard(InvocationContext ic) throws Exception { long maxNbrOfFailures = FAILURES_COUNT; long timeout = TIMEOUT_IN_MS; IgnoreCallsWhen configuration = ic. getMethod(). getAnnotation(IgnoreCallsWhen.class); if (configuration != null) { maxNbrOfFailures = configuration.failures(); timeout = configuration.slowerThanMillis(); } long start = System.currentTimeMillis(); try { if (errorCounter >= maxNbrOfFailures) { return null; } return ic.proceed(); } catch (Exception ex) { errorCounter++; throw ex; } finally { long duration = System.currentTimeMillis() - start; if (duration >= timeout) { errorCounter++; } } } }

The threshold can be easily configured with an annotation:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface IgnoreCallsWhen { long slowerThanMillis() default 1000; long failures() default 3; }

Usage example:

@Singleton @Interceptors(Breakr.class) public class Slow { @IgnoreCallsWhen(slowerThanMillis = 10) public String tooSlow() { try { Thread.sleep(100); } catch (InterruptedException ex) {} return "Slow: " + System.currentTimeMillis(); } }

The source is available from github.com/AdamBien/breakr.

Use the following maven dependency to install breakr:

<dependency> <groupId>com.airhacks</groupId> <artifactId>breakr</artifactId> <version>[CURRENT_VERSION]</version> </dependency>