Search in sources :

Example 1 with Bulkhead

use of io.github.resilience4j.bulkhead.Bulkhead in project resilience4j by resilience4j.

the class BulkheadMetricsTest method shouldUseCustomPrefix.

@Test
public void shouldUseCustomPrefix() throws Throwable {
    // Given
    BulkheadRegistry bulkheadRegistry = BulkheadRegistry.ofDefaults();
    Bulkhead bulkhead = bulkheadRegistry.bulkhead("testBulkhead");
    metricRegistry.registerAll(BulkheadMetrics.ofIterable("testPre", bulkheadRegistry.getAllBulkheads()));
    // Given latch to verify bulkhead
    CountDownLatch countDownLatch = new CountDownLatch(1);
    // Given the HelloWorldService returns Hello world
    BDDMockito.given(helloWorldService.returnHelloWorld()).will(invocation -> {
        if (countDownLatch.await(10, TimeUnit.SECONDS)) {
            return "Hello world";
        } else {
            throw new IllegalStateException("Timeout - test failure");
        }
    });
    // When
    Future<String> future = executorService.submit(() -> bulkhead.executeSupplier(helloWorldService::returnHelloWorld));
    // Then metrics are present and show value
    assertThat(metricRegistry.getMetrics()).hasSize(1);
    assertThat(metricRegistry.getGauges().get("testPre.testBulkhead.available_concurrent_calls").getValue()).isIn(DEFAULT_MAX_CONCURRENT_CALLS, DEFAULT_MAX_CONCURRENT_CALLS - 1);
    // Then release latch and verify result
    countDownLatch.countDown();
    assertThat(future.get(10, TimeUnit.SECONDS)).isEqualTo("Hello world");
    BDDMockito.then(helloWorldService).should(times(1)).returnHelloWorld();
    // Then check metrics again
    assertThat(metricRegistry.getMetrics()).hasSize(1);
    assertThat(metricRegistry.getGauges().get("testPre.testBulkhead.available_concurrent_calls").getValue()).isIn(DEFAULT_MAX_CONCURRENT_CALLS, DEFAULT_MAX_CONCURRENT_CALLS);
}
Also used : Bulkhead(io.github.resilience4j.bulkhead.Bulkhead) BulkheadRegistry(io.github.resilience4j.bulkhead.BulkheadRegistry) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Example 2 with Bulkhead

use of io.github.resilience4j.bulkhead.Bulkhead in project resilience4j by resilience4j.

the class BulkheadTransformer method apply.

@Override
public Upstream<T> apply(Upstream<? extends T> upstream) throws Exception {
    return down -> {
        if (bulkhead.isCallPermitted()) {
            // do not allow permits to leak
            upstream.connect(new Downstream<T>() {

                @Override
                public void success(T value) {
                    bulkhead.onComplete();
                    down.success(value);
                }

                @Override
                public void error(Throwable throwable) {
                    bulkhead.onComplete();
                    try {
                        if (recover != null) {
                            down.success(recover.apply(throwable));
                        } else {
                            down.error(throwable);
                        }
                    } catch (Throwable t) {
                        down.error(t);
                    }
                }

                @Override
                public void complete() {
                    bulkhead.onComplete();
                    down.complete();
                }
            });
        } else {
            Throwable t = new BulkheadFullException(String.format("Bulkhead '%s' is full", bulkhead.getName()));
            if (recover != null) {
                try {
                    down.success(recover.apply(t));
                } catch (Throwable t2) {
                    down.error(t2);
                }
            } else {
                down.error(t);
            }
        }
    };
}
Also used : Downstream(ratpack.exec.Downstream) Function(ratpack.func.Function) BulkheadFullException(io.github.resilience4j.bulkhead.BulkheadFullException) Bulkhead(io.github.resilience4j.bulkhead.Bulkhead) Upstream(ratpack.exec.Upstream) BulkheadFullException(io.github.resilience4j.bulkhead.BulkheadFullException) Downstream(ratpack.exec.Downstream)

Example 3 with Bulkhead

use of io.github.resilience4j.bulkhead.Bulkhead in project resilience4j by resilience4j.

the class BulkheadChain method execute.

@Override
public void execute(Chain chain) throws Exception {
    String prefix = chain.getRegistry().get(Resilience4jConfig.class).getEndpoints().getBulkheads().getPath();
    chain.prefix(prefix, chain1 -> {
        chain1.get("events", ctx -> Promise.<BulkheadEventsEndpointResponse>async(d -> {
            BulkheadEventsEndpointResponse response = new BulkheadEventsEndpointResponse(eventConsumerRegistry.getAllEventConsumer().flatMap(CircularEventConsumer::getBufferedEvents).sorted(Comparator.comparing(BulkheadEvent::getCreationTime)).map(BulkheadEventDTO::createEventDTO).toJavaList());
            d.success(response);
        }).then(r -> ctx.render(Jackson.json(r))));
        chain1.get("stream/events", ctx -> {
            Seq<Flowable<BulkheadEvent>> eventStreams = bulkheadRegistry.getAllBulkheads().map(bulkhead -> RxJava2Adapter.toFlowable(bulkhead.getEventPublisher()));
            Function<BulkheadEvent, String> data = b -> Jackson.getObjectWriter(chain1.getRegistry()).writeValueAsString(BulkheadEventDTO.createEventDTO(b));
            ServerSentEvents events = ServerSentEvents.serverSentEvents(Flowable.merge(eventStreams), e -> e.id(BulkheadEvent::getBulkheadName).event(c -> c.getEventType().name()).data(data));
            ctx.render(events);
        });
        chain1.get("events/:name", ctx -> {
            String bulkheadName = ctx.getPathTokens().get("name");
            Promise.<BulkheadEventsEndpointResponse>async(d -> {
                BulkheadEventsEndpointResponse response = new BulkheadEventsEndpointResponse(eventConsumerRegistry.getEventConsumer(bulkheadName).getBufferedEvents().map(BulkheadEventDTO::createEventDTO).toJavaList());
                d.success(response);
            }).then(r -> ctx.render(Jackson.json(r)));
        });
        chain1.get("stream/events/:name", ctx -> {
            String bulkheadName = ctx.getPathTokens().get("name");
            Bulkhead bulkhead = bulkheadRegistry.getAllBulkheads().find(b -> b.getName().equals(bulkheadName)).getOrElseThrow(() -> new IllegalArgumentException(String.format("bulkhead with name %s not found", bulkheadName)));
            Function<BulkheadEvent, String> data = b -> Jackson.getObjectWriter(chain1.getRegistry()).writeValueAsString(BulkheadEventDTO.createEventDTO(b));
            ServerSentEvents events = ServerSentEvents.serverSentEvents(RxJava2Adapter.toFlowable(bulkhead.getEventPublisher()), e -> e.id(BulkheadEvent::getBulkheadName).event(c -> c.getEventType().name()).data(data));
            ctx.render(events);
        });
        chain1.get("events/:name/:type", ctx -> {
            String bulkheadName = ctx.getPathTokens().get("name");
            String eventType = ctx.getPathTokens().get("type");
            Promise.<BulkheadEventsEndpointResponse>async(d -> {
                BulkheadEventsEndpointResponse response = new BulkheadEventsEndpointResponse(eventConsumerRegistry.getEventConsumer(bulkheadName).getBufferedEvents().filter(event -> event.getEventType() == BulkheadEvent.Type.valueOf(eventType.toUpperCase())).map(BulkheadEventDTO::createEventDTO).toJavaList());
                d.success(response);
            }).then(r -> ctx.render(Jackson.json(r)));
        });
        chain1.get("stream/events/:name/:type", ctx -> {
            String bulkheadName = ctx.getPathTokens().get("name");
            String eventType = ctx.getPathTokens().get("type");
            Bulkhead bulkhead = bulkheadRegistry.getAllBulkheads().find(b -> b.getName().equals(bulkheadName)).getOrElseThrow(() -> new IllegalArgumentException(String.format("bulkhead with name %s not found", bulkheadName)));
            Flowable<BulkheadEvent> eventStream = RxJava2Adapter.toFlowable(bulkhead.getEventPublisher()).filter(event -> event.getEventType() == BulkheadEvent.Type.valueOf(eventType.toUpperCase()));
            Function<BulkheadEvent, String> data = b -> Jackson.getObjectWriter(chain1.getRegistry()).writeValueAsString(BulkheadEventDTO.createEventDTO(b));
            ServerSentEvents events = ServerSentEvents.serverSentEvents(eventStream, e -> e.id(BulkheadEvent::getBulkheadName).event(c -> c.getEventType().name()).data(data));
            ctx.render(events);
        });
    });
}
Also used : Function(ratpack.func.Function) RxJava2Adapter(io.github.resilience4j.adapter.RxJava2Adapter) BulkheadRegistry(io.github.resilience4j.bulkhead.BulkheadRegistry) Bulkhead(io.github.resilience4j.bulkhead.Bulkhead) Promise(ratpack.exec.Promise) BulkheadEvent(io.github.resilience4j.bulkhead.event.BulkheadEvent) Resilience4jConfig(io.github.resilience4j.ratpack.Resilience4jConfig) Jackson(ratpack.jackson.Jackson) ServerSentEvents(ratpack.sse.ServerSentEvents) Chain(ratpack.handling.Chain) Inject(javax.inject.Inject) Flowable(io.reactivex.Flowable) CircularEventConsumer(io.github.resilience4j.consumer.CircularEventConsumer) Action(ratpack.func.Action) Seq(io.vavr.collection.Seq) Comparator(java.util.Comparator) EventConsumerRegistry(io.github.resilience4j.consumer.EventConsumerRegistry) Resilience4jConfig(io.github.resilience4j.ratpack.Resilience4jConfig) BulkheadEvent(io.github.resilience4j.bulkhead.event.BulkheadEvent) Bulkhead(io.github.resilience4j.bulkhead.Bulkhead) CircularEventConsumer(io.github.resilience4j.consumer.CircularEventConsumer) ServerSentEvents(ratpack.sse.ServerSentEvents) Flowable(io.reactivex.Flowable)

Example 4 with Bulkhead

use of io.github.resilience4j.bulkhead.Bulkhead in project resilience4j by resilience4j.

the class BulkheadMetricsTest method shouldRegisterMetrics.

@Test
public void shouldRegisterMetrics() throws Throwable {
    // Given
    BulkheadRegistry bulkheadRegistry = BulkheadRegistry.ofDefaults();
    Bulkhead bulkhead = bulkheadRegistry.bulkhead("testBulkhead");
    metricRegistry.registerAll(BulkheadMetrics.ofBulkhead(bulkhead));
    // Given latch to verify bulkhead
    CountDownLatch countDownLatch = new CountDownLatch(1);
    // Given the HelloWorldService returns Hello world
    BDDMockito.given(helloWorldService.returnHelloWorld()).will(invocation -> {
        if (countDownLatch.await(10, TimeUnit.SECONDS)) {
            return "Hello world";
        } else {
            throw new IllegalStateException("Timeout - test failure");
        }
    });
    // When
    Future<String> future = executorService.submit(() -> bulkhead.executeSupplier(helloWorldService::returnHelloWorld));
    // Then metrics are present and show value
    assertThat(metricRegistry.getMetrics()).hasSize(1);
    assertThat(metricRegistry.getGauges().get("resilience4j.bulkhead.testBulkhead.available_concurrent_calls").getValue()).isIn(DEFAULT_MAX_CONCURRENT_CALLS, DEFAULT_MAX_CONCURRENT_CALLS - 1);
    // Then release latch and verify result
    countDownLatch.countDown();
    assertThat(future.get(10, TimeUnit.SECONDS)).isEqualTo("Hello world");
    BDDMockito.then(helloWorldService).should(times(1)).returnHelloWorld();
    // Then check metrics again
    assertThat(metricRegistry.getMetrics()).hasSize(1);
    assertThat(metricRegistry.getGauges().get("resilience4j.bulkhead.testBulkhead.available_concurrent_calls").getValue()).isIn(DEFAULT_MAX_CONCURRENT_CALLS, DEFAULT_MAX_CONCURRENT_CALLS);
}
Also used : Bulkhead(io.github.resilience4j.bulkhead.Bulkhead) BulkheadRegistry(io.github.resilience4j.bulkhead.BulkheadRegistry) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.Test)

Example 5 with Bulkhead

use of io.github.resilience4j.bulkhead.Bulkhead in project resilience4j by resilience4j.

the class BulkheadMetrics method bindTo.

@Override
public void bindTo(MeterRegistry registry) {
    for (Bulkhead bulkhead : bulkheads) {
        final String name = bulkhead.getName();
        Gauge.builder(getName(prefix, name, AVAILABLE_CONCURRENT_CALLS), bulkhead, (cb) -> cb.getMetrics().getAvailableConcurrentCalls()).register(registry);
    }
}
Also used : BulkheadRegistry(io.github.resilience4j.bulkhead.BulkheadRegistry) Gauge(io.micrometer.core.instrument.Gauge) DEFAULT_PREFIX(io.github.resilience4j.bulkhead.utils.MetricNames.DEFAULT_PREFIX) MetricUtils.getName(io.github.resilience4j.micrometer.MetricUtils.getName) MeterRegistry(io.micrometer.core.instrument.MeterRegistry) Objects.requireNonNull(java.util.Objects.requireNonNull) Bulkhead(io.github.resilience4j.bulkhead.Bulkhead) MeterBinder(io.micrometer.core.instrument.binder.MeterBinder) AVAILABLE_CONCURRENT_CALLS(io.github.resilience4j.bulkhead.utils.MetricNames.AVAILABLE_CONCURRENT_CALLS) Bulkhead(io.github.resilience4j.bulkhead.Bulkhead)

Aggregations

Bulkhead (io.github.resilience4j.bulkhead.Bulkhead)7 BulkheadRegistry (io.github.resilience4j.bulkhead.BulkheadRegistry)4 Test (org.junit.Test)4 CountDownLatch (java.util.concurrent.CountDownLatch)2 Function (ratpack.func.Function)2 RxJava2Adapter (io.github.resilience4j.adapter.RxJava2Adapter)1 BulkheadConfig (io.github.resilience4j.bulkhead.BulkheadConfig)1 BulkheadFullException (io.github.resilience4j.bulkhead.BulkheadFullException)1 BulkheadEvent (io.github.resilience4j.bulkhead.event.BulkheadEvent)1 AVAILABLE_CONCURRENT_CALLS (io.github.resilience4j.bulkhead.utils.MetricNames.AVAILABLE_CONCURRENT_CALLS)1 DEFAULT_PREFIX (io.github.resilience4j.bulkhead.utils.MetricNames.DEFAULT_PREFIX)1 CircularEventConsumer (io.github.resilience4j.consumer.CircularEventConsumer)1 EventConsumerRegistry (io.github.resilience4j.consumer.EventConsumerRegistry)1 MetricUtils.getName (io.github.resilience4j.micrometer.MetricUtils.getName)1 Resilience4jConfig (io.github.resilience4j.ratpack.Resilience4jConfig)1 Gauge (io.micrometer.core.instrument.Gauge)1 MeterRegistry (io.micrometer.core.instrument.MeterRegistry)1 MeterBinder (io.micrometer.core.instrument.binder.MeterBinder)1 Flowable (io.reactivex.Flowable)1 Seq (io.vavr.collection.Seq)1