Interface CircuitBreakerProvider


public interface CircuitBreakerProvider
Escape hatch for RipClientConfig.Builder.circuitBreaker(CircuitBreakerProvider) - delegates the actual open/closed decision to an already-running circuit breaker instance (resilience4j or otherwise) instead of RIP's own built-in CircuitBreakerConfig-driven state machine. See docs/design/circuit-breaker-bulkhead.md ยง5 for the full "build-your-own default, pluggable override" reasoning - RIP never takes a hard dependency on resilience4j (or anything else) to support this; only this small SPI, which a consumer implements themselves.
 CircuitBreaker r4jBreaker = CircuitBreaker.ofDefaults("payment-api");

 RipClientConfig config = RipClientConfig.builder()
         .circuitBreaker(new CircuitBreakerProvider() {
             public boolean tryAcquirePermission() {
                 return r4jBreaker.tryAcquirePermission();
             }
             public void onSuccess(long durationNanos, int statusCode) {
                 if (statusCode >= 500) {
                     r4jBreaker.onError(durationNanos, TimeUnit.NANOSECONDS,
                             new RuntimeException("HTTP " + statusCode));
                 } else {
                     r4jBreaker.onSuccess(durationNanos, TimeUnit.NANOSECONDS);
                 }
             }
             public void onError(long durationNanos, Throwable t) {
                 r4jBreaker.onError(durationNanos, TimeUnit.NANOSECONDS, t);
             }
         })
         .build();
 UserApi api = RIP.getClient(UserApi.class, config);
 

Only comes into play when explicitly configured this way - a client configured with CircuitBreakerConfig instead uses RIP's own built-in implementation, unaffected. Setting one clears the other on the builder, the same "last call wins" shape CircuitBreakerConfig.Builder's own overloaded slidingWindowSize setters already use.

  • Method Summary

    Modifier and Type
    Method
    Description
    void
    onError(long durationNanos, Throwable t)
    Called once a permitted call fails at the transport level (a connection refused, a timeout - no response at all).
    void
    onSuccess(long durationNanos, int statusCode)
    Called once a permitted call completes with an actual HTTP response - any status code, since RIP itself makes no assumption about what an external breaker considers a failure.
    boolean
    Called before every attempt (once per @Retry attempt too, the same per-attempt granularity RIP's own built-in breaker uses) to ask whether the call should proceed at all.
  • Method Details

    • tryAcquirePermission

      boolean tryAcquirePermission()
      Called before every attempt (once per @Retry attempt too, the same per-attempt granularity RIP's own built-in breaker uses) to ask whether the call should proceed at all. Assumed non-blocking - the same assumption resilience4j's own CircuitBreaker#tryAcquirePermission() makes - so it's called directly on the caller's thread on both the sync and async dispatch paths.
      Returns:
      true to let the call proceed; false to refuse it immediately with a CircuitOpenException, without ever attempting the network call
    • onSuccess

      void onSuccess(long durationNanos, int statusCode)
      Called once a permitted call completes with an actual HTTP response - any status code, since RIP itself makes no assumption about what an external breaker considers a failure. Classify statusCode yourself (as the example above does) if the underlying breaker's own config expects a failing status reported through onError(long, java.lang.Throwable) instead.
      Parameters:
      durationNanos - how long the call took
      statusCode - the response's HTTP status code
    • onError

      void onError(long durationNanos, Throwable t)
      Called once a permitted call fails at the transport level (a connection refused, a timeout - no response at all).
      Parameters:
      durationNanos - how long the call took before failing
      t - the transport-level failure