This project is now hosted by resilience4j. https://github.com/resilience4j/resilience4j
Ratpack support for resilience4j. https://github.com/resilience4j/resilience4j
compile 'me.drmaas:ratpack-resilience4j:x.x.x'
<dependency>
<groupId>me.drmaas</groupId>
<artifactId>ratpack-resilience4j</artifactId>
<version>x.x.x/version>
</dependency>
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofMillis(1000))
.ringBufferSizeInHalfOpenState(2)
.ringBufferSizeInClosedState(2)
.build()
CircuitBreaker breaker = CircuitBreaker.of("test", config)
CircuitBreakerTransformer<String> transformer = CircuitBreakerTransformer.of(breaker).recover { t -> "bar" }
def r = ExecHarness.yieldSingle {
Blocking.<String>get {
throw new Exception("test")
}.transform(transformer)
}
r.value == "bar"
breaker.state == CircuitBreaker.State.CLOSED
r = ExecHarness.yieldSingle {
Blocking.<String>get {
throw e
}.transform(transformer)
}
r.value == "bar"
breaker.state == CircuitBreaker.State.OPEN
RetryConfig config = RetryConfig.custom()
.maxAttempts(3)
.waitDuration(Duration.ofMillis(500))
.build()
Retry rate = Retry.of("test", config)
RetryTransformer<String> transformer = RetryTransformer.of(rate).recover { t -> "bar" }
AtomicInteger times = new AtomicInteger(0)
when:
def r = ExecHarness.yieldSingle {
Blocking.<String>get {
times.getAndIncrement()
throw new Exception("test")
}.transform(transformer)
}
then:
r.value == "bar"
times.get() == 3
Simply set up the circuit breaker registry and register your circuit breakers before binding the registry. The annotation will look up your circuit breaker by name.
The annotation is tested for Promise, Observable, Flowable, CompletionStage, and generic Object types.
ratpack {
bindings {
bindInstance(CircuitBreakerRegistry, someRegistry)
bind(Something)
module(ResilienceModule)
}
handlers {
get('promise') { Something something ->
something.breakerPromise().then {
render it
}
}
}
}
class Something {
@Breaker(name = "test", recovery = MyRecoveryFunction)
Promise<String> breakerPromise() {
Promise.async {
it.error(new Exception("grrr"))
}
}
}
class MyRecoveryFunction implements RecoveryFunction<String> {
@Override
String apply(Throwable t) throws Exception {
"recovered"
}
}