Class CircuitBreaker

java.lang.Object
org.apache.pekko.pattern.CircuitBreaker

public class CircuitBreaker extends Object
Provides circuit breaker functionality for stability when working with "dangerous" operations, e.g. calls to remote systems.

Transitions through three states: - In *Closed* state, calls pass through until the maxFailures count is reached. This causes the circuit breaker to open. Both exceptions and calls exceeding callTimeout are considered failures. - In *Open* state, calls fail-fast with an exception. After resetTimeout, circuit breaker transitions to half-open state. - In *Half-Open* state, the first call will be allowed through, if it succeeds the circuit breaker will reset to closed state. If it fails, the circuit breaker will re-open to open state. All calls beyond the first that execute while the first is running will fail-fast with an exception.

param: scheduler Reference to Pekko scheduler param: maxFailures Maximum number of failures before opening the circuit param: callTimeout FiniteDuration of time after which to consider a call a failure param: resetTimeout FiniteDuration of time after which to attempt to close the circuit param: randomFactor after calculation of the exponential back-off an additional random delay based on this factor is added, e.g. 0.2 adds up to 20% delay. randomFactor should be in range 0.0 (inclusive) and 1.0 (inclusive). In order to skip this additional delay pass in 0. param: executor ExecutionContext used for execution of state transition listeners

  • Field Details

    • stateHandle

      protected static final VarHandle stateHandle
    • resetTimeoutHandle

      protected static final VarHandle resetTimeoutHandle
  • Constructor Details

    • CircuitBreaker

      public CircuitBreaker(Scheduler scheduler, int maxFailures, scala.concurrent.duration.FiniteDuration callTimeout, scala.concurrent.duration.FiniteDuration resetTimeout, scala.concurrent.duration.FiniteDuration maxResetTimeout, double exponentialBackoffFactor, double randomFactor, scala.collection.immutable.Set<String> allowExceptions, CircuitBreakerTelemetry telemetry, scala.concurrent.ExecutionContext executor)
    • CircuitBreaker

      public CircuitBreaker(Scheduler scheduler, int maxFailures, scala.concurrent.duration.FiniteDuration callTimeout, scala.concurrent.duration.FiniteDuration resetTimeout, scala.concurrent.duration.FiniteDuration maxResetTimeout, double exponentialBackoffFactor, double randomFactor, scala.concurrent.ExecutionContext executor)
    • CircuitBreaker

      public CircuitBreaker(scala.concurrent.ExecutionContext executor, Scheduler scheduler, int maxFailures, Duration callTimeout, Duration resetTimeout)
    • CircuitBreaker

      public CircuitBreaker(Scheduler scheduler, int maxFailures, scala.concurrent.duration.FiniteDuration callTimeout, scala.concurrent.duration.FiniteDuration resetTimeout, scala.concurrent.ExecutionContext executor)
    • CircuitBreaker

      public CircuitBreaker(Scheduler scheduler, int maxFailures, scala.concurrent.duration.FiniteDuration callTimeout, scala.concurrent.duration.FiniteDuration resetTimeout, scala.concurrent.duration.FiniteDuration maxResetTimeout, double exponentialBackoffFactor, scala.concurrent.ExecutionContext executor)
  • Method Details

    • apply

      public static CircuitBreaker apply(Scheduler scheduler, int maxFailures, scala.concurrent.duration.FiniteDuration callTimeout, scala.concurrent.duration.FiniteDuration resetTimeout)
      Create a new CircuitBreaker.

      Callbacks run in caller's thread when using withSyncCircuitBreaker, and in same ExecutionContext as the passed in Future when using withCircuitBreaker. To use another ExecutionContext for the callbacks you can specify the executor in the constructor.

      Parameters:
      scheduler - Reference to Pekko scheduler
      maxFailures - Maximum number of failures before opening the circuit
      callTimeout - FiniteDuration of time after which to consider a call a failure
      resetTimeout - FiniteDuration of time after which to attempt to close the circuit
    • apply

      public static CircuitBreaker apply(String id, ExtendedActorSystem system)
      Create or find a CircuitBreaker in registry.

      Parameters:
      id - Circuit Breaker identifier
      system - ExtendedActorSystem that is storing this CircuitBreaker
    • create

      public static CircuitBreaker create(Scheduler scheduler, int maxFailures, Duration callTimeout, Duration resetTimeout)
      Java API: Create a new CircuitBreaker.

      Callbacks run in caller's thread when using withSyncCircuitBreaker, and in same ExecutionContext as the passed in Future when using withCircuitBreaker. To use another ExecutionContext for the callbacks you can specify the executor in the constructor.

      Parameters:
      scheduler - Reference to Pekko scheduler
      maxFailures - Maximum number of failures before opening the circuit
      callTimeout - Duration of time after which to consider a call a failure
      resetTimeout - Duration of time after which to attempt to close the circuit
    • lookup

      public static CircuitBreaker lookup(String id, ExtendedActorSystem system)
      Java API: Lookup a CircuitBreaker in registry.

      Parameters:
      id - Circuit Breaker identifier
      system - ExtendedActorSystem that is storing this CircuitBreaker
    • convertJavaFailureFnToScala

      protected static <T> scala.Function1<scala.util.Try<T>,Object> convertJavaFailureFnToScala(BiFunction<Optional<T>,Optional<Throwable>,Boolean> javaFn)
    • resetTimeout

      public scala.concurrent.duration.FiniteDuration resetTimeout()
    • allowExceptions

      public scala.collection.immutable.Set<String> allowExceptions()
    • telemetry

      public CircuitBreakerTelemetry telemetry()
    • withExponentialBackoff

      public CircuitBreaker withExponentialBackoff(scala.concurrent.duration.FiniteDuration maxResetTimeout)
      The resetTimeout will be increased exponentially for each failed attempt to close the circuit. The default exponential backoff factor is 2.

      Parameters:
      maxResetTimeout - the upper bound of resetTimeout
    • withExponentialBackoff

      public CircuitBreaker withExponentialBackoff(Duration maxResetTimeout)
      The resetTimeout will be increased exponentially for each failed attempt to close the circuit. The default exponential backoff factor is 2.

      Parameters:
      maxResetTimeout - the upper bound of resetTimeout
    • withRandomFactor

      public CircuitBreaker withRandomFactor(double randomFactor)
      Adds jitter to the delay.
      Parameters:
      randomFactor - after calculation of the back-off an additional random delay based on this factor is added, e.g. 0.2 adds up to 20% delay. In order to skip this additional delay pass in 0.
    • withCircuitBreaker

      public <T> scala.concurrent.Future<T> withCircuitBreaker(scala.Function0<scala.concurrent.Future<T>> body, scala.Function1<scala.util.Try<T>,Object> defineFailureFn)
      Wraps invocations of asynchronous calls that need to be protected.

      Parameters:
      body - Call needing protected
      defineFailureFn - function that define what should be consider failure and thus increase failure count
      Returns:
      Future containing the call result or a scala.concurrent.TimeoutException if the call timed out
    • withCircuitBreaker

      public <T> scala.concurrent.Future<T> withCircuitBreaker(scala.Function0<scala.concurrent.Future<T>> body)
      Wraps invocations of asynchronous calls that need to be protected.

      Parameters:
      body - Call needing protected
      Returns:
      Future containing the call result or a scala.concurrent.TimeoutException if the call timed out
    • callWithCircuitBreaker

      public <T> scala.concurrent.Future<T> callWithCircuitBreaker(Callable<scala.concurrent.Future<T>> body)
      Parameters:
      body - Call needing protected
      Returns:
      Future containing the call result or a scala.concurrent.TimeoutException if the call timed out
    • callWithCircuitBreaker

      public <T> scala.concurrent.Future<T> callWithCircuitBreaker(Callable<scala.concurrent.Future<T>> body, BiFunction<Optional<T>,Optional<Throwable>,Boolean> defineFailureFn)
      Parameters:
      body - Call needing protected
      defineFailureFn - function that define what should be consider failure and thus increase failure count
      Returns:
      Future containing the call result or a scala.concurrent.TimeoutException if the call timed out
    • callWithCircuitBreakerCS

      public <T> CompletionStage<T> callWithCircuitBreakerCS(Callable<CompletionStage<T>> body)
      Parameters:
      body - Call needing protected
      Returns:
      CompletionStage containing the call result or a scala.concurrent.TimeoutException if the call timed out
    • callWithCircuitBreakerCS

      public <T> CompletionStage<T> callWithCircuitBreakerCS(Callable<CompletionStage<T>> body, BiFunction<Optional<T>,Optional<Throwable>,Boolean> defineFailureFn)
      Parameters:
      body - Call needing protected
      defineFailureFn - function that define what should be consider failure and thus increase failure count
      Returns:
      CompletionStage containing the call result or a scala.concurrent.TimeoutException if the call timed out
    • withSyncCircuitBreaker

      public <T> T withSyncCircuitBreaker(scala.Function0<T> body)
      Wraps invocations of synchronous calls that need to be protected.

      Calls are run in the caller's thread. Because of the synchronous nature of this call, the scala.concurrent.TimeoutException will only be thrown after the body has completed.

      Throws java.util.concurrent.TimeoutException if the call timed out.

      Parameters:
      body - Call needing protected
      Returns:
      The result of the call
    • withSyncCircuitBreaker

      public <T> T withSyncCircuitBreaker(scala.Function0<T> body, scala.Function1<scala.util.Try<T>,Object> defineFailureFn)
      Wraps invocations of synchronous calls that need to be protected.

      Calls are run in caller's thread. Because of the synchronous nature of this call the scala.concurrent.TimeoutException will only be thrown after the body has completed.

      Throws java.util.concurrent.TimeoutException if the call timed out.

      Parameters:
      body - Call needing protected
      defineFailureFn - function that define what should be consider failure and thus increase failure count
      Returns:
      The result of the call
    • callWithSyncCircuitBreaker

      public <T> T callWithSyncCircuitBreaker(Callable<T> body)
      Java API for withSyncCircuitBreaker(scala.Function0<T>). Throws TimeoutException if the call timed out.

      Parameters:
      body - Call needing protected
      Returns:
      The result of the call
    • callWithSyncCircuitBreaker

      public <T> T callWithSyncCircuitBreaker(Callable<T> body, BiFunction<Optional<T>,Optional<Throwable>,Boolean> defineFailureFn)
      Java API for withSyncCircuitBreaker(scala.Function0<T>). Throws TimeoutException if the call timed out.

      Parameters:
      body - Call needing protected
      defineFailureFn - function that define what should be consider failure and thus increase failure count
      Returns:
      The result of the call
    • succeed

      public void succeed()
      Mark a successful call through CircuitBreaker. Sometimes the callee of CircuitBreaker sends back a message to the caller Actor. In such a case, it is convenient to mark a successful call instead of using Future via <T>withCircuitBreaker(scala.Function0<scala.concurrent.Future<T>>,scala.Function1<scala.util.Try<T>,java.lang.Object>)
    • fail

      public void fail()
      Mark a failed call through CircuitBreaker. Sometimes the callee of CircuitBreaker sends back a message to the caller Actor. In such a case, it is convenient to mark a failed call instead of using Future via <T>withCircuitBreaker(scala.Function0<scala.concurrent.Future<T>>,scala.Function1<scala.util.Try<T>,java.lang.Object>)
    • isClosed

      public boolean isClosed()
      Return true if the internal state is Closed. WARNING: It is a "power API" call which you should use with care. Ordinal use cases of CircuitBreaker expects a remote call to return Future, as in withCircuitBreaker. So, if you check the state by yourself, and make a remote call outside CircuitBreaker, you should manage the state yourself.
    • isOpen

      public boolean isOpen()
      Return true if the internal state is Open. WARNING: It is a "power API" call which you should use with care. Ordinal use cases of CircuitBreaker expects a remote call to return Future, as in withCircuitBreaker. So, if you check the state by yourself, and make a remote call outside CircuitBreaker, you should manage the state yourself.
    • isHalfOpen

      public boolean isHalfOpen()
      Return true if the internal state is HalfOpen. WARNING: It is a "power API" call which you should use with care. Ordinal use cases of CircuitBreaker expects a remote call to return Future, as in withCircuitBreaker. So, if you check the state by yourself, and make a remote call outside CircuitBreaker, you should manage the state yourself.
    • onOpen

      public CircuitBreaker onOpen(scala.Function0<scala.runtime.BoxedUnit> callback)
      Adds a callback to execute when circuit breaker opens

      The callback is run in the ExecutionContext supplied in the constructor.

      Parameters:
      callback - Handler to be invoked on state change
      Returns:
      CircuitBreaker for fluent usage
    • addOnOpenListener

      public CircuitBreaker addOnOpenListener(Runnable callback)
      Java API for onOpen

      Parameters:
      callback - Handler to be invoked on state change
      Returns:
      CircuitBreaker for fluent usage
    • onHalfOpen

      public CircuitBreaker onHalfOpen(scala.Function0<scala.runtime.BoxedUnit> callback)
      Adds a callback to execute when circuit breaker transitions to half-open The callback is run in the ExecutionContext supplied in the constructor.

      Parameters:
      callback - Handler to be invoked on state change
      Returns:
      CircuitBreaker for fluent usage
    • addOnHalfOpenListener

      public CircuitBreaker addOnHalfOpenListener(Runnable callback)
      JavaAPI for onHalfOpen

      Parameters:
      callback - Handler to be invoked on state change
      Returns:
      CircuitBreaker for fluent usage
    • onClose

      public CircuitBreaker onClose(scala.Function0<scala.runtime.BoxedUnit> callback)
      Adds a callback to execute when circuit breaker state closes

      The callback is run in the ExecutionContext supplied in the constructor.

      Parameters:
      callback - Handler to be invoked on state change
      Returns:
      CircuitBreaker for fluent usage
    • addOnCloseListener

      public CircuitBreaker addOnCloseListener(Runnable callback)
      JavaAPI for onClose

      Parameters:
      callback - Handler to be invoked on state change
      Returns:
      CircuitBreaker for fluent usage
    • onCallSuccess

      public CircuitBreaker onCallSuccess(scala.Function1<Object,scala.runtime.BoxedUnit> callback)
      Adds a callback to execute when call finished with success.

      The callback is run in the ExecutionContext supplied in the constructor.

      Parameters:
      callback - Handler to be invoked on successful call, where passed value is elapsed time in nanoseconds.
      Returns:
      CircuitBreaker for fluent usage
    • addOnCallSuccessListener

      public CircuitBreaker addOnCallSuccessListener(Consumer<Object> callback)
      JavaAPI for onCallSuccess

      Parameters:
      callback - Handler to be invoked on successful call, where passed value is elapsed time in nanoseconds.
      Returns:
      CircuitBreaker for fluent usage
    • onCallFailure

      public CircuitBreaker onCallFailure(scala.Function1<Object,scala.runtime.BoxedUnit> callback)
      Adds a callback to execute if the call finished with failure.

      The callback is run in the ExecutionContext supplied in the constructor.

      Parameters:
      callback - Handler to be invoked on failed call, where passed value is elapsed time in nanoseconds.
      Returns:
      CircuitBreaker for fluent usage
    • addOnCallFailureListener

      public CircuitBreaker addOnCallFailureListener(Consumer<Object> callback)
      JavaAPI for onCallFailure.

      Parameters:
      callback - Handler to be invoked on failed call, where passed value is elapsed time in nanoseconds.
      Returns:
      CircuitBreaker for fluent usage
    • onCallTimeout

      public CircuitBreaker onCallTimeout(scala.Function1<Object,scala.runtime.BoxedUnit> callback)
      Adds a callback to execute if a call finished with timeout.

      The callback is run in the ExecutionContext supplied in the constructor.

      Parameters:
      callback - Handler to be invoked on call finished with timeout, where passed value is elapsed time in nanoseconds.
      Returns:
      CircuitBreaker for fluent usage
    • addOnCallTimeoutListener

      public CircuitBreaker addOnCallTimeoutListener(Consumer<Object> callback)
      JavaAPI for onCallTimeout.

      Parameters:
      callback - Handler to be invoked on call finished with timeout, where passed value is elapsed time in nanoseconds.
      Returns:
      CircuitBreaker for fluent usage
    • onCallBreakerOpen

      public CircuitBreaker onCallBreakerOpen(scala.Function0<scala.runtime.BoxedUnit> callback)
      Adds a callback to execute if call was failed due to open breaker.

      The callback is run in the ExecutionContext supplied in the constructor.

      Parameters:
      callback - Handler to be invoked on call failed due to open breaker.
      Returns:
      CircuitBreaker for fluent usage
    • addOnCallBreakerOpenListener

      public CircuitBreaker addOnCallBreakerOpenListener(Runnable callback)
      JavaAPI for onCallBreakerOpen.

      Parameters:
      callback - Handler to be invoked on call failed due to open breaker.
      Returns:
      CircuitBreaker for fluent usage