@Override protected Throwable getThrowable() { return new CircuitBreakerOpenException( String.format("CircuitBreaker '%s' is open", circuitBreaker.getName())); }
@Override protected void hookOnPermitAcquired() { stopWatch = StopWatch.start(circuitBreaker.getName()); }
private Exception circuitBreakerOpenException() { return new CircuitBreakerOpenException(String.format("CircuitBreaker '%s' is open", circuitBreaker.getName())); }
private boolean acquireCallPermit() { boolean callPermitted = false; if (permitted.compareAndSet(Permit.PENDING, Permit.ACQUIRED)) { callPermitted = circuitBreaker.isCallPermitted(); if (!callPermitted) { permitted.set(Permit.REJECTED); } else { stopWatch = StopWatch.start(circuitBreaker.getName()); } } return callPermitted; }
private boolean acquireCallPermit() { boolean callPermitted = false; if (permitted.compareAndSet(Permit.PENDING, Permit.ACQUIRED)) { callPermitted = circuitBreaker.isCallPermitted(); if (!callPermitted) { permitted.set(Permit.REJECTED); } else { stopWatch = StopWatch.start(circuitBreaker.getName()); } } return callPermitted; }
public static void isCallPermitted(CircuitBreaker circuitBreaker) { if(!circuitBreaker.isCallPermitted()) { throw new CircuitBreakerOpenException(String.format("CircuitBreaker '%s' is open", circuitBreaker.getName())); } } }
@RequestMapping(value = "stream/events/{circuitBreakerName}", produces = MEDIA_TYPE_TEXT_EVENT_STREAM) public SseEmitter getEventsStreamFilteredByCircuitBreakerName(@PathVariable("circuitBreakerName") String circuitBreakerName) { CircuitBreaker circuitBreaker = circuitBreakerRegistry.getAllCircuitBreakers() .find(cb -> cb.getName().equals(circuitBreakerName)) .getOrElseThrow(() -> new IllegalArgumentException(String.format("circuit breaker with name %s not found", circuitBreakerName))); return CircuitBreakerEventEmitter.createSseEmitter(toFlux(circuitBreaker.getEventPublisher())); }
@Override public void onSubscribe(Subscription subscription) { if (SubscriptionHelper.setOnce(this, subscription)) { if (acquireCallPermit()) { childSubscriber.onSubscribe(this); } else { cancel(); childSubscriber.onSubscribe(this); childSubscriber.onError(new CircuitBreakerOpenException(String.format("CircuitBreaker '%s' is open", circuitBreaker.getName()))); } } }
@RequestMapping(value = "stream/events/{circuitBreakerName}/{eventType}", produces = MEDIA_TYPE_TEXT_EVENT_STREAM) public SseEmitter getEventsStreamFilteredByCircuitBreakerNameAndEventType(@PathVariable("circuitBreakerName") String circuitBreakerName, @PathVariable("eventType") String eventType) { CircuitBreaker circuitBreaker = circuitBreakerRegistry.getAllCircuitBreakers() .find(cb -> cb.getName().equals(circuitBreakerName)) .getOrElseThrow(() -> new IllegalArgumentException(String.format("circuit breaker with name %s not found", circuitBreakerName))); Flux<CircuitBreakerEvent> eventStream = toFlux(circuitBreaker.getEventPublisher()) .filter(event -> event.getEventType() == CircuitBreakerEvent.Type.valueOf(eventType.toUpperCase())); return CircuitBreakerEventEmitter.createSseEmitter(eventStream); }
private CircuitBreakerMetrics(String prefix, Iterable<CircuitBreaker> circuitBreakers) { requireNonNull(prefix); requireNonNull(circuitBreakers); circuitBreakers.forEach((CircuitBreaker circuitBreaker) -> { String name = circuitBreaker.getName(); //state as an integer metricRegistry.register(name(prefix, name, STATE), (Gauge<Integer>)()-> circuitBreaker.getState().getOrder()); metricRegistry.register(name(prefix, name, SUCCESSFUL), (Gauge<Integer>) () -> circuitBreaker.getMetrics().getNumberOfSuccessfulCalls()); metricRegistry.register(name(prefix, name, FAILED), (Gauge<Integer>) () -> circuitBreaker.getMetrics().getNumberOfFailedCalls()); metricRegistry.register(name(prefix, name, NOT_PERMITTED), (Gauge<Long>) () -> circuitBreaker.getMetrics().getNumberOfNotPermittedCalls()); metricRegistry.register(name(prefix, name, BUFFERED), (Gauge<Integer>) () -> circuitBreaker.getMetrics().getNumberOfBufferedCalls()); metricRegistry.register(name(prefix, name, BUFFERED_MAX), (Gauge<Integer>) () -> circuitBreaker.getMetrics().getMaxNumberOfBufferedCalls()); } ); }
@Override public void enqueue(final Callback<T> callback) { try { CircuitBreakerUtils.isCallPermitted(circuitBreaker); } catch (CircuitBreakerOpenException cb) { callback.onFailure(call, cb); return; } final StopWatch stopWatch = StopWatch.start(circuitBreaker.getName()); call.enqueue(new Callback<T>() { @Override public void onResponse(final Call<T> call, final Response<T> response) { if (responseSuccess.test(response)) { circuitBreaker.onSuccess(stopWatch.stop().getProcessingDuration().toNanos()); } else { final Throwable throwable = new Throwable("Response error: HTTP " + response.code() + " - " + response.message()); circuitBreaker.onError(stopWatch.stop().getProcessingDuration().toNanos(), throwable); } callback.onResponse(call, response); } @Override public void onFailure(final Call<T> call, final Throwable t) { circuitBreaker.onError(stopWatch.stop().getProcessingDuration().toNanos(), t); callback.onFailure(call, t); } }); }
future.fail( new CircuitBreakerOpenException( String.format("CircuitBreaker '%s' is open", circuitBreaker.getName())));
promise.completeExceptionally( new CircuitBreakerOpenException( String.format("CircuitBreaker '%s' is open", circuitBreaker.getName())));
final double value = state == circuitBreaker.getState() ? 1.0 : 0.0; states.addMetric(asList(circuitBreaker.getName(), name), value); }); asList(circuitBreaker.getName(), "successful"), metrics.getNumberOfSuccessfulCalls()); asList(circuitBreaker.getName(), "failed"), metrics.getNumberOfFailedCalls()); asList(circuitBreaker.getName(), "not_permitted"), metrics.getNumberOfNotPermittedCalls()); asList(circuitBreaker.getName(), "buffered"), metrics.getNumberOfBufferedCalls()); asList(circuitBreaker.getName(), "buffered_max"), metrics.getMaxNumberOfBufferedCalls());
@Override public Upstream<T> apply(Upstream<? extends T> upstream) throws Exception { return down -> { long start; if (circuitBreaker.isCallPermitted()) { start = System.nanoTime(); upstream.connect(new Downstream<T>() { @Override public void success(T value) { long durationInNanos = System.nanoTime() - start; circuitBreaker.onSuccess(durationInNanos); down.success(value); } @Override public void error(Throwable throwable) { long durationInNanos = System.nanoTime() - start; circuitBreaker.onError(durationInNanos, throwable); handleRecovery(down, throwable); } @Override public void complete() { down.complete(); } }); } else { Throwable t = new CircuitBreakerOpenException(String.format("CircuitBreaker '%s' is open", circuitBreaker.getName())); handleRecovery(down, t); } }; }
@Test public void shouldReturnTheCorrectName() { assertThat(circuitBreaker.getName()).isEqualTo("testName"); }
@Override public Response<T> execute() throws IOException { CircuitBreakerUtils.isCallPermitted(circuitBreaker); final StopWatch stopWatch = StopWatch.start(circuitBreaker.getName()); try { final Response<T> response = call.execute(); if (responseSuccess.test(response)) { circuitBreaker.onSuccess(stopWatch.stop().getProcessingDuration().toNanos()); } else { final Throwable throwable = new Throwable("Response error: HTTP " + response.code() + " - " + response.message()); circuitBreaker.onError(stopWatch.stop().getProcessingDuration().toNanos(), throwable); } return response; } catch (Throwable throwable) { circuitBreaker.onError(stopWatch.stop().getProcessingDuration().toNanos(), throwable); throw throwable; } } };
@Test public void shouldReturnTheCorrectName() { CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("testName"); assertThat(circuitBreaker).isNotNull(); assertThat(circuitBreaker.getName()).isEqualTo("testName"); }
chain1.get("stream/events/:name", ctx -> { String circuitBreakerName = ctx.getPathTokens().get("name"); CircuitBreaker circuitBreaker = circuitBreakerRegistry.getAllCircuitBreakers().find(cb -> cb.getName().equals(circuitBreakerName)) .getOrElseThrow(() -> new IllegalArgumentException(String.format("circuit breaker with name %s not found", circuitBreakerName))); Function<CircuitBreakerEvent, String> data = c -> Jackson.getObjectWriter(chain1.getRegistry()).writeValueAsString(CircuitBreakerEventDTOFactory.createCircuitBreakerEventDTO(c)); String circuitBreakerName = ctx.getPathTokens().get("name"); String eventType = ctx.getPathTokens().get("type"); CircuitBreaker circuitBreaker = circuitBreakerRegistry.getAllCircuitBreakers().find(cb -> cb.getName().equals(circuitBreakerName)) .getOrElseThrow(() -> new IllegalArgumentException(String.format("circuit breaker with name %s not found", circuitBreakerName))); Flux<CircuitBreakerEvent> eventStream = ReactorAdapter.toFlux(circuitBreaker.getEventPublisher())
@Override public void bindTo(MeterRegistry registry) { for (CircuitBreaker circuitBreaker : circuitBreakers) { final String name = circuitBreaker.getName(); Gauge.builder(getName(prefix, name, STATE), circuitBreaker, (cb) -> cb.getState().getOrder()) .register(registry); Gauge.builder(getName(prefix, name, BUFFERED_MAX), circuitBreaker, (cb) -> cb.getMetrics().getMaxNumberOfBufferedCalls()) .register(registry); Gauge.builder(getName(prefix, name, BUFFERED), circuitBreaker, (cb) -> cb.getMetrics().getNumberOfBufferedCalls()) .register(registry); Gauge.builder(getName(prefix, name, FAILED), circuitBreaker, (cb) -> cb.getMetrics().getNumberOfFailedCalls()) .register(registry); Gauge.builder(getName(prefix, name, NOT_PERMITTED), circuitBreaker, (cb) -> cb.getMetrics().getNumberOfNotPermittedCalls()) .register(registry); Gauge.builder(getName(prefix, name, SUCCESSFUL), circuitBreaker, (cb) -> cb.getMetrics().getNumberOfSuccessfulCalls()) .register(registry); } } }