Updated documentation

Updated documentation

== Usage Guide

=== Configure the CircuitBreaker

This library comes with an `InMemoryCircuitBreakerRegistry` based on a `ConcurrentMap` which provides thread safety and atomicity guarantees. You must use the CircuitBreakerRegistry to manage (create and retrieve) your CircuitBreakers. You can create a `InMemoryCircuitBreakerRegistry` with a default global `CircuitBreakerConfig` for all of your CircuitBreakers as follows.

[source,java]
----
// Create a InMemoryCircuitBreakerRegistry with a default global configuration
// (maxFailures = 3, waitInterval = 60[s], ignoredExceptions = empty)
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
----

As an alternative you can provide your own custom global `CircuitBreakerConfig`. In order to create a custom global CircuitBreakerConfig or a CircuitBreakerConfig for a specific CircuitBreaker, you can use the CircuitBreakerConfig builder. You can configure the maximum number of allowed failures and the wait interval [ms], which specifies how long the CircuitBreaker should stay in state `OPEN`.

[source,java]
----
// Create a custom configuration for a CircuitBreaker
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
    .maxFailures(1)
    .waitInterval(1000)
    .build();

// Create a InMemoryCircuitBreakerRegistry with a custom global configuration
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig);

// Get a CircuitBreaker from the CircuitBreakerRegistry with the global default configuration
CircuitBreaker circuitBreaker2 = circuitBreakerRegistry.circuitBreaker("otherName");

// Get a CircuitBreaker from the CircuitBreakerRegistry with a custom configuration
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName", circuitBreakerConfig);
----

=== Functional programming example

You can decorate any `Supplier / Runnable / Function` or `CheckedSupplier / CheckedRunnable / CheckedFunction` function with `CircuitBreaker.decorateCheckedSupplier()`, `CircuitBreaker.decorateCheckedRunnable()` or `CircuitBreaker.decorateCheckedFunction()`. You can invoke the returned function with `Try.of()` or `Try.run()` from https://github.com/javaslang/javaslang[javaslang]. This allows to chain further functions with `map`, `flatMap`, `filter`, `recover` or `andThen`. The chained functions are only invoked, if the CircuitBreaker is CLOSED or HALF_CLOSED.
In the following example, `Try.of()` returns a `Success<String>` Monad, if the invocation of the function is successful. If the function throws an exception, a `Failure<Throwable>` Monad is returned and `map` is not invoked.

[source,java]
----
// Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName");

// When
Try.CheckedSupplier<String> decoratedSupplier = CircuitBreaker
        .decorateCheckedSupplier(() -> "This can be any method which returns: 'Hello", circuitBreaker);

// You can chain other functions with `map` and `flatMap`.
// The `Try` Monad returns a `Success<String>`, if all functions run successfully.
Try<String> result = Try.of(decoratedSupplier)
                .map(value -> value + " world'");

// Then
assertThat(result.isSuccess()).isTrue();
assertThat(result.get()).isEqualTo("This can be any method which returns: 'Hello world'");
----

You could also chain up functions which are decorated by different CircuitBreakers.

[source,java]
----
//Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("testName");
CircuitBreaker anotherCircuitBreaker = circuitBreakerRegistry.circuitBreaker("anotherTestName");

// When I create a Supplier and a Function which are decorated by different CircuitBreakers
Try.CheckedSupplier<String> decoratedSupplier = CircuitBreaker
        .decorateCheckedSupplier(() -> "Hello", circuitBreaker);

Try.CheckedFunction<String, String> decoratedFunction = CircuitBreaker
        .decorateCheckedFunction((input) -> input + " world", anotherCircuitBreaker);

// and I chain a function with `map`.
Try<String> result = Try.of(decoratedSupplier)
        .map(decoratedFunction);

// Then
assertThat(result.get()).isEqualTo("Hello world");
----

=== OPEN CircuitBreaker example

In this test case `map` is not invoked, because the CircuitBreaker is OPEN. The call to `Try.of` returns a `Failure<Throwable>` Monad so that the chained function is not invoked.

[source,java]
----
// Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
// Create a custom configration so that only 1 failure is allowed and the wait interval is 1[s]
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
    .maxFailures(1)
    .waitInterval(1000)
    .build();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName", circuitBreakerConfig);

// CircuitBreaker is initially CLOSED
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
// Simulate a failure attempt
circuitBreaker.recordFailure(new RuntimeException());
// CircuitBreaker is still CLOSED, because 1 failure is allowed
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
// Simulate a failure attempt
circuitBreaker.recordFailure(new RuntimeException());
// CircuitBreaker is OPEN, because maxFailures > 1
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.OPEN);

// When I decorate my function and invoke the decorated function
Try<String> result = Try.of(CircuitBreaker.decorateCheckedSupplier(() -> "Hello", circuitBreaker))
        .map(value -> value + " world");

// Then the call fails, because CircuitBreaker is OPEN
assertThat(result.isFailure()).isTrue();
// and the exception is a CircuitBreakerOpenException
assertThat(result.failed().get()).isInstanceOf(CircuitBreakerOpenException.class);
----

=== Recover from an exception

If you want to recover from any exception, you can chain the method `Try.recover()`. The recovery method is only invoked, if `Try.of()` returns a `Failure<Throwable>` Monad.

[source,java]
----
//Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName");

// When I decorate my function and invoke the decorated function
Try.CheckedSupplier<String> checkedSupplier = CircuitBreaker.decorateCheckedSupplier(() -> {
        Thread.sleep(1000);
        throw new RuntimeException("BAM!");
    }, circuitBreaker);
Try<String> result = Try.of(checkedSupplier)
        .recover((throwable) -> "Hello Recovery");

//Then the function should be a success, because the exception could be recovered
assertThat(result.isSuccess()).isTrue();
// and the result must match the result of the recovery function.
assertThat(result.get()).isEqualTo("Hello Recovery");
----

=== Customize exception handler
The default exception handler counts all type of exceptions as failures and triggers the CircuitBreaker. If you want to use a custom exception handler, you have to implement the functional interface `Predicate` which has a method `test`. The Predicate must return true if the exception should count as a failure, otherwise it must return false.
The following example shows how to ignore an `IOException`, but all other exception types still count as failures.

[source,java,indent=0]
----
include::../../test/java/io/github/robwin/circuitbreaker/CircuitBreakerTest.java[tags=shouldNotTriggerCircuitBreakerOpenException]
----

=== Customize event listener
The default event listener logs state transitions with INFO level.

----
INFO  i.g.r.c.i.DefaultCircuitBreakerEventListener - CircuitBreaker 'testName' changes state from CLOSED to OPEN
----

If you want to use a custom event listener, you have to implement the functional interface `CircuitBreakerEventListener` which has a method `onCircuitBreakerEvent(CircuitBreakerEvent circuitBreakerEvent)`. The only event which currently exists is `CircuitBreakerStateTransitionEvent`.

[source,java]
----
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
    .onCircuitBreakerEvent((event) -> LOG.info(event.toString()))
    .build();
----

=== Retry a failed function

You can also retry a failed function and recover from the exception, if the maximum retry count was reached. You can create a `Retry` context using a default configuration as follows.

[source,java]
----
// Create a Retry context with a default global configuration
// (maxAttempts = 3, waitInterval = 500[ms], ignoredExceptions = empty)
Retry retryContext = Retry.ofDefaults();
----

In order to create a custom `Retry` context, you can use the Retry context builder. You can configure the maximum number of retry attempts and the wait interval [ms] between successive attempts. Furthermore, you can add exceptions to the ignore list which must not trigger a retry.

[source,java]
----
Retry retryContext = Retry.custom()
    .maxAttempts(2)
    .waitInterval(1000)
    .onException(throwable -> Match.of(throwable)
        .whenType(WebServiceException.class).then(false)
        .otherwise(true).get())
    .build();
----

You can decorate any `Supplier / Runnable / Function` or `CheckedSupplier / CheckedRunnable / CheckedFunction` function with `Retry.retryableCheckedSupplier()`, `Retry.retryableCheckedRunnable()` or `Retry.retryableCheckedFunction()`.

[source,java]
----
// Given I have a HelloWorldService which throws an exception
HelloWorldService  helloWorldService = mock(HelloWorldService.class);
given(helloWorldService.sayHelloWorld()).willThrow(new WebServiceException("BAM!"));

// Create a Retry with default configuration
// (maxAttempts = 3, waitInterval = 500[ms], ignoredExceptions = empty)
Retry retryContext = Retry.ofDefaults();
// Decorate the invocation of the HelloWorldService
Try.CheckedSupplier<String> retryableSupplier = Retry.retryableCheckedSupplier(helloWorldService::sayHelloWorld, retryContext);

// When I invoke the function
Try<String> result = Try.of(retryableSupplier).recover((throwable) -> "Hello world from recovery function");

// Then the helloWorldService should be invoked 3 times
BDDMockito.then(helloWorldService).should(times(3)).sayHelloWorld();
// and the exception should be handled by the recovery function
assertThat(result.get()).isEqualTo("Hello world from recovery function");
----

=== CompletableFuture example

You can also invoke a decorated function asynchronously by using a `CompletableFuture` and chain further functions.

[source,java]
----
// Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("testName");

// When
Supplier<String> decoratedSupplier = CircuitBreaker
        .decorateSupplier(() -> "This can be any method which returns: 'Hello", circuitBreaker);

CompletableFuture<String> future = CompletableFuture.supplyAsync(decoratedSupplier)
        .thenApply(value -> value + " world'");

//Then
assertThat(future.get()).isEqualTo("This can be any method which returns: 'Hello world'");
----

=== Reactive Streams example

You can also invoke a decorated function asynchronously by using a Reactive Streams implementation like https://github.com/ReactiveX/RxJava[RxJava] or https://github.com/reactor/reactor/[Project Reactor].

[source,java]
----
 // Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("testName");
// CircuitBreaker is initially CLOSED
circuitBreaker.recordFailure(new RuntimeException());
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
// CircuitBreaker is still CLOSED, because 1 failure is allowed
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
circuitBreaker.recordFailure(new RuntimeException());
// CircuitBreaker is OPEN, because maxFailures > 1
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.OPEN);

// Decorate the supplier of the HelloWorldService with CircuitBreaker functionality
Supplier<String> supplier = CircuitBreaker.decorateSupplier(() -> "Hello world", circuitBreaker);

//When I consume from a reactive stream it should forward the CircuitBreakerOpenException.
Streams.generate(supplier::get)
        .map(value -> value + " from reactive streams")
        .consume(value -> {
            LOG.info(value);
        }, exception -> {
            LOG.info("Exception handled: " + exception.toString());
            assertThat(exception).isInstanceOf(CircuitBreakerOpenException.class);
        });
----

=== Example with Dropwizard Metrics

You can use https://dropwizard.github.io/metrics/[Dropwizard Metrics] to get runtime metrics of your functions. The project provides several higher-order functions to decorate any `Supplier / Runnable / Function` or `CheckedSupplier / CheckedRunnable / CheckedFunction`. The decorator creates a histogram and a meter for your function.  A histogram measures min, mean, max, standard deviation and quantiles like the median or 95th percentile of the execution time. A meter measures the rate of executions.

[source,java]
----
// Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName");
MetricRegistry metricRegistry = new MetricRegistry();
Timer timer = metricRegistry.timer(name("test"));

// When I create a long running supplier which takes 2 seconds
Try.CheckedSupplier<String> supplier = () -> {
    Thread.sleep(2000);
    return "Hello world";
};

// and decorate the supplier with a Metrics timer
Try.CheckedSupplier<String> timedSupplier = Metrics.timedCheckedSupplier(supplier, timer);

// and decorate the supplier with a CircuitBreaker
Try.CheckedSupplier<String> circuitBreakerAndTimedSupplier = CircuitBreaker
        .decorateCheckedSupplier(timedSupplier, circuitBreaker);

String value = circuitBreakerAndTimedSupplier.get();

// Then the Metrics execution counter should be 1
assertThat(timer.getCount()).isEqualTo(1);
// and the mean time should be greater than 2[s]
assertThat(timer.getSnapshot().getMean()).isGreaterThan(2);

assertThat(value).isEqualTo("Hello world");
----

== Usage Guide

=== Configure the CircuitBreaker

This library comes with an `InMemoryCircuitBreakerRegistry` based on a `ConcurrentMap` which provides thread safety and atomicity guarantees. You must use the CircuitBreakerRegistry to manage (create and retrieve) your CircuitBreakers. You can create a `InMemoryCircuitBreakerRegistry` with a default global `CircuitBreakerConfig` for all of your CircuitBreakers as follows.

[source,java]
----
// Create a InMemoryCircuitBreakerRegistry with a default global configuration
// (maxFailures = 3, waitInterval = 60[s], ignoredExceptions = empty)
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
----

As an alternative you can provide your own custom global `CircuitBreakerConfig`. In order to create a custom global CircuitBreakerConfig or a CircuitBreakerConfig for a specific CircuitBreaker, you can use the CircuitBreakerConfig builder. You can configure the maximum number of allowed failures and the wait interval [ms], which specifies how long the CircuitBreaker should stay in state `OPEN`. Furthermore, you can add exceptions to the ignore list which must not trigger the CircuitBreaker.

[source,java]
----
// Create a custom configuration for a CircuitBreaker
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
    .maxFailures(1)
    .waitInterval(1000)
    .ignoredException(BusinessException.class)
    .ignoredException(AnotherBusinessException.class)
    .build();

// Create a InMemoryCircuitBreakerRegistry with a custom global configuration
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig);

// Get a CircuitBreaker from the CircuitBreakerRegistry with the global default configuration
CircuitBreaker circuitBreaker2 = circuitBreakerRegistry.circuitBreaker("otherName");

// Get a CircuitBreaker from the CircuitBreakerRegistry with a custom configuration
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName", circuitBreakerConfig);
----

=== Functional programming example

You can decorate any `Supplier / Runnable / Function` or `CheckedSupplier / CheckedRunnable / CheckedFunction` function with `CircuitBreaker.decorateCheckedSupplier()`, `CircuitBreaker.decorateCheckedRunnable()` or `CircuitBreaker.decorateCheckedFunction()`. You can invoke the returned function with `Try.of()` or `Try.run()` from https://github.com/javaslang/javaslang[javaslang]. This allows to chain further functions with `map`, `flatMap`, `filter`, `recover` or `andThen`. The chained functions are only invoked, if the CircuitBreaker is CLOSED or HALF_CLOSED.
In the following example, `Try.of()` returns a `Success<String>` Monad, if the invocation of the function is successful. If the function throws an exception, a `Failure<Throwable>` Monad is returned and `map` is not invoked.

[source,java]
----
// Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName");

// When
Try.CheckedSupplier<String> decoratedSupplier = CircuitBreaker
        .decorateCheckedSupplier(() -> "This can be any method which returns: 'Hello", circuitBreaker);

// You can chain other functions with `map` and `flatMap`.
// The `Try` Monad returns a `Success<String>`, if all functions run successfully.
Try<String> result = Try.of(decoratedSupplier)
                .map(value -> value + " world'");

// Then
assertThat(result.isSuccess()).isTrue();
assertThat(result.get()).isEqualTo("This can be any method which returns: 'Hello world'");
----

You could also chain up functions which are decorated by different CircuitBreakers.

[source,java]
----
//Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("testName");
CircuitBreaker anotherCircuitBreaker = circuitBreakerRegistry.circuitBreaker("anotherTestName");

// When I create a Supplier and a Function which are decorated by different CircuitBreakers
Try.CheckedSupplier<String> decoratedSupplier = CircuitBreaker
        .decorateCheckedSupplier(() -> "Hello", circuitBreaker);

Try.CheckedFunction<String, String> decoratedFunction = CircuitBreaker
        .decorateCheckedFunction((input) -> input + " world", anotherCircuitBreaker);

// and I chain a function with `map`.
Try<String> result = Try.of(decoratedSupplier)
        .map(decoratedFunction);

// Then
assertThat(result.get()).isEqualTo("Hello world");
----

=== OPEN CircuitBreaker example

In this test case `map` is not invoked, because the CircuitBreaker is OPEN. The call to `Try.of` returns a `Failure<Throwable>` Monad so that the chained function is not invoked.

[source,java]
----
// Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
// Create a custom configration so that only 1 failure is allowed and the wait interval is 1[s]
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
    .maxFailures(1)
    .waitInterval(1000)
    .build();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName", circuitBreakerConfig);

// CircuitBreaker is initially CLOSED
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
// Simulate a failure attempt
circuitBreaker.recordFailure(new RuntimeException());
// CircuitBreaker is still CLOSED, because 1 failure is allowed
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
// Simulate a failure attempt
circuitBreaker.recordFailure(new RuntimeException());
// CircuitBreaker is OPEN, because maxFailures > 1
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.OPEN);

// When I decorate my function and invoke the decorated function
Try<String> result = Try.of(CircuitBreaker.decorateCheckedSupplier(() -> "Hello", circuitBreaker))
        .map(value -> value + " world");

// Then the call fails, because CircuitBreaker is OPEN
assertThat(result.isFailure()).isTrue();
// and the exception is a CircuitBreakerOpenException
assertThat(result.failed().get()).isInstanceOf(CircuitBreakerOpenException.class);
----

=== Recover from an exception

If you want to recover from any exception, you can chain the method `Try.recover()`. The recovery method is only invoked, if `Try.of()` returns a `Failure<Throwable>` Monad.

[source,java]
----
//Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName");

// When I decorate my function and invoke the decorated function
Try.CheckedSupplier<String> checkedSupplier = CircuitBreaker.decorateCheckedSupplier(() -> {
        Thread.sleep(1000);
        throw new RuntimeException("BAM!");
    }, circuitBreaker);
Try<String> result = Try.of(checkedSupplier)
        .recover((throwable) -> "Hello Recovery");

//Then the function should be a success, because the exception could be recovered
assertThat(result.isSuccess()).isTrue();
// and the result must match the result of the recovery function.
assertThat(result.get()).isEqualTo("Hello Recovery");
----

=== Customize exception handler
The default exception handler counts all type of exceptions as failures and triggers the CircuitBreaker. If you want to use a custom exception handler, you have to implement the functional interface `Predicate` which has a method `test`. The Predicate must return true if the exception should count as a failure, otherwise it must return false.
The following example shows how to ignore an `IOException`, but all other exception types still count as failures.

[source,java,indent=0]
----
include::../../test/java/io/github/robwin/circuitbreaker/CircuitBreakerTest.java[tags=shouldNotTriggerCircuitBreakerOpenException]
----

=== Customize event listener
The default event listener logs state transitions with INFO level.

----
INFO  i.g.r.c.i.DefaultCircuitBreakerEventListener - CircuitBreaker 'testName' changes state from CLOSED to OPEN
----

If you want to use a custom event listener, you have to implement the functional interface `CircuitBreakerEventListener` which has a method `onCircuitBreakerEvent(CircuitBreakerEvent circuitBreakerEvent)`. The only event which currently exists is `CircuitBreakerStateTransitionEvent`.

[source,java]
----
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
    .onCircuitBreakerEvent((event) -> LOG.info(event.toString()))
    .build();
----

=== Retry a failed function

You can also retry a failed function and recover from the exception, if the maximum retry count was reached. You can create a `Retry` context using a default configuration as follows.

[source,java]
----
// Create a Retry context with a default global configuration
// (maxAttempts = 3, waitInterval = 500[ms], ignoredExceptions = empty)
Retry retryContext = Retry.ofDefaults();
----

In order to create a custom `Retry` context, you can use the Retry context builder. You can configure the maximum number of retry attempts and the wait interval [ms] between successive attempts. Furthermore, you can add exceptions to the ignore list which must not trigger a retry.

[source,java]
----
Retry retryContext = Retry.custom()
    .maxAttempts(2)
    .waitInterval(1000)
    .onException(throwable -> Match.of(throwable)
        .whenType(WebServiceException.class).then(false)
        .otherwise(true).get())
    .build();
----

You can decorate any `Supplier / Runnable / Function` or `CheckedSupplier / CheckedRunnable / CheckedFunction` function with `Retry.retryableCheckedSupplier()`, `Retry.retryableCheckedRunnable()` or `Retry.retryableCheckedFunction()`.

[source,java]
----
// Given I have a HelloWorldService which throws an exception
HelloWorldService  helloWorldService = mock(HelloWorldService.class);
given(helloWorldService.sayHelloWorld()).willThrow(new WebServiceException("BAM!"));

// Create a Retry with default configuration
// (maxAttempts = 3, waitInterval = 500[ms], ignoredExceptions = empty)
Retry retryContext = Retry.ofDefaults();
// Decorate the invocation of the HelloWorldService
Try.CheckedSupplier<String> retryableSupplier = Retry.retryableCheckedSupplier(helloWorldService::sayHelloWorld, retryContext);

// When I invoke the function
Try<String> result = Try.of(retryableSupplier).recover((throwable) -> "Hello world from recovery function");

// Then the helloWorldService should be invoked 3 times
BDDMockito.then(helloWorldService).should(times(3)).sayHelloWorld();
// and the exception should be handled by the recovery function
assertThat(result.get()).isEqualTo("Hello world from recovery function");
----

=== CompletableFuture example

You can also invoke a decorated function asynchronously by using a `CompletableFuture` and chain further functions.

[source,java]
----
// Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("testName");

// When
Supplier<String> decoratedSupplier = CircuitBreaker
        .decorateSupplier(() -> "This can be any method which returns: 'Hello", circuitBreaker);

CompletableFuture<String> future = CompletableFuture.supplyAsync(decoratedSupplier)
        .thenApply(value -> value + " world'");

//Then
assertThat(future.get()).isEqualTo("This can be any method which returns: 'Hello world'");
----

=== Reactive Streams example

You can also invoke a decorated function asynchronously by using a Reactive Streams implementation like https://github.com/ReactiveX/RxJava[RxJava] or https://github.com/reactor/reactor/[Project Reactor].

[source,java]
----
 // Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("testName");
// CircuitBreaker is initially CLOSED
circuitBreaker.recordFailure(new RuntimeException());
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
// CircuitBreaker is still CLOSED, because 1 failure is allowed
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
circuitBreaker.recordFailure(new RuntimeException());
// CircuitBreaker is OPEN, because maxFailures > 1
assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.OPEN);

// Decorate the supplier of the HelloWorldService with CircuitBreaker functionality
Supplier<String> supplier = CircuitBreaker.decorateSupplier(() -> "Hello world", circuitBreaker);

//When I consume from a reactive stream it should forward the CircuitBreakerOpenException.
Streams.generate(supplier::get)
        .map(value -> value + " from reactive streams")
        .consume(value -> {
            LOG.info(value);
        }, exception -> {
            LOG.info("Exception handled: " + exception.toString());
            assertThat(exception).isInstanceOf(CircuitBreakerOpenException.class);
        });
----

=== Example with Dropwizard Metrics

You can use https://dropwizard.github.io/metrics/[Dropwizard Metrics] to get runtime metrics of your functions. The project provides several higher-order functions to decorate any `Supplier / Runnable / Function` or `CheckedSupplier / CheckedRunnable / CheckedFunction`. The decorator creates a histogram and a meter for your function.  A histogram measures min, mean, max, standard deviation and quantiles like the median or 95th percentile of the execution time. A meter measures the rate of executions.

[source,java]
----
// Given
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("uniqueName");
MetricRegistry metricRegistry = new MetricRegistry();
Timer timer = metricRegistry.timer(name("test"));

// When I create a long running supplier which takes 2 seconds
Try.CheckedSupplier<String> supplier = () -> {
    Thread.sleep(2000);
    return "Hello world";
};

// and decorate the supplier with a Metrics timer
Try.CheckedSupplier<String> timedSupplier = Metrics.timedCheckedSupplier(supplier, timer);

// and decorate the supplier with a CircuitBreaker
Try.CheckedSupplier<String> circuitBreakerAndTimedSupplier = CircuitBreaker
        .decorateCheckedSupplier(timedSupplier, circuitBreaker);

String value = circuitBreakerAndTimedSupplier.get();

// Then the Metrics execution counter should be 1
assertThat(timer.getCount()).isEqualTo(1);
// and the mean time should be greater than 2[s]
assertThat(timer.getSnapshot().getMean()).isGreaterThan(2);

assertThat(value).isEqualTo("Hello world");
----


Upgrade source cluster to lastest z-stream release


Update 2016-02-06-.adoc

Update 2016-02-06-.adoc


fix smart quotes

fix smart quotes