io.vavr.CheckedFunction0 Java Examples
The following examples show how to use
io.vavr.CheckedFunction0.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SupplierRetryTest.java From resilience4j with Apache License 2.0 | 7 votes |
@Test public void shouldReturnAfterOneAttemptAndIgnoreException() { given(helloWorldService.returnHelloWorld()).willThrow(new HelloWorldException()); RetryConfig config = RetryConfig.custom() .retryOnException(throwable -> API.Match(throwable).of( API.Case($(Predicates.instanceOf(HelloWorldException.class)), false), API.Case($(), true))) .build(); Retry retry = Retry.of("id", config); CheckedFunction0<String> retryableSupplier = Retry .decorateCheckedSupplier(retry, helloWorldService::returnHelloWorld); Try<String> result = Try.of(retryableSupplier); // Because the exception should be rethrown immediately. then(helloWorldService).should().returnHelloWorld(); assertThat(result.isFailure()).isTrue(); assertThat(result.failed().get()).isInstanceOf(HelloWorldException.class); assertThat(sleptTime).isEqualTo(0); }
Example #2
Source File: DecoratorsTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void testDecorateCheckedSupplier() throws IOException { given(helloWorldService.returnHelloWorldWithException()).willReturn("Hello world"); CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("helloBackend"); CheckedFunction0<String> decoratedSupplier = Decorators .ofCheckedSupplier(() -> helloWorldService.returnHelloWorldWithException()) .withCircuitBreaker(circuitBreaker) .withRetry(Retry.ofDefaults("id")) .withRateLimiter(RateLimiter.ofDefaults("testName")) .withBulkhead(Bulkhead.ofDefaults("testName")) .decorate(); String result = Try.of(decoratedSupplier).get(); assertThat(result).isEqualTo("Hello world"); CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics(); assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(1); assertThat(metrics.getNumberOfSuccessfulCalls()).isEqualTo(1); then(helloWorldService).should(times(1)).returnHelloWorldWithException(); }
Example #3
Source File: SupplierRetryTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void shouldTakeIntoAccountBackoffFunction() { given(helloWorldService.returnHelloWorld()).willThrow(new HelloWorldException()); RetryConfig config = RetryConfig.custom() .intervalFunction(IntervalFunction.ofExponentialBackoff(500, 2.0)) .build(); Retry retry = Retry.of("id", config); CheckedFunction0<String> retryableSupplier = Retry .decorateCheckedSupplier(retry, helloWorldService::returnHelloWorld); Try.of(retryableSupplier); then(helloWorldService).should(times(3)).returnHelloWorld(); assertThat(sleptTime).isEqualTo( RetryConfig.DEFAULT_WAIT_DURATION + RetryConfig.DEFAULT_WAIT_DURATION * 2); }
Example #4
Source File: SupplierRetryTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void shouldReturnAfterThreeAttemptsAndRecoverWithResult() { given(helloWorldService.returnHelloWorld()) .willThrow(new HelloWorldException()) .willReturn("Hello world") .willThrow(new HelloWorldException()); final RetryConfig tryAgain = RetryConfig.<String>custom() .retryOnResult(s -> s.contains("Hello world")) .maxAttempts(3).build(); Retry retry = Retry.of("id", tryAgain); CheckedFunction0<String> retryableSupplier = Retry .decorateCheckedSupplier(retry, helloWorldService::returnHelloWorld); Try<String> result = Try.of(retryableSupplier) .recover((throwable) -> "Hello world from recovery function"); then(helloWorldService).should(times(3)).returnHelloWorld(); assertThat(result.get()).isEqualTo("Hello world from recovery function"); assertThat(sleptTime).isEqualTo(RetryConfig.DEFAULT_WAIT_DURATION * 2); }
Example #5
Source File: RateLimiterTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void decorateCheckedSupplier() throws Throwable { CheckedFunction0 supplier = mock(CheckedFunction0.class); CheckedFunction0 decorated = RateLimiter.decorateCheckedSupplier(limit, supplier); given(limit.acquirePermission(1)).willReturn(false); Try decoratedSupplierResult = Try.of(decorated); assertThat(decoratedSupplierResult.isFailure()).isTrue(); assertThat(decoratedSupplierResult.getCause()).isInstanceOf(RequestNotPermitted.class); then(supplier).should(never()).apply(); given(limit.acquirePermission(1)).willReturn(true); Try secondSupplierResult = Try.of(decorated); assertThat(secondSupplierResult.isSuccess()).isTrue(); then(supplier).should().apply(); }
Example #6
Source File: CircuitBreakerTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void shouldDecorateCheckedSupplierAndReturnWithSuccess() throws Throwable { CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults(); CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("testName"); CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics(); assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(0); given(helloWorldService.returnHelloWorldWithException()).willReturn("Hello world"); CheckedFunction0<String> checkedSupplier = circuitBreaker .decorateCheckedSupplier(helloWorldService::returnHelloWorldWithException); String result = checkedSupplier.apply(); assertThat(result).isEqualTo("Hello world"); assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(1); assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(0); assertThat(metrics.getNumberOfSuccessfulCalls()).isEqualTo(1); then(helloWorldService).should().returnHelloWorldWithException(); }
Example #7
Source File: CircuitBreakerTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void shouldDecorateCheckedSupplierAndReturnWithException() throws Throwable { CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults(); CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("testName"); CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics(); assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(0); given(helloWorldService.returnHelloWorldWithException()) .willThrow(new RuntimeException("BAM!")); CheckedFunction0<String> checkedSupplier = circuitBreaker .decorateCheckedSupplier(helloWorldService::returnHelloWorldWithException); Try<String> result = Try.of(checkedSupplier); assertThat(result.isFailure()).isTrue(); assertThat(result.failed().get()).isInstanceOf(RuntimeException.class); assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(1); assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(1); assertThat(metrics.getNumberOfSuccessfulCalls()).isEqualTo(0); then(helloWorldService).should().returnHelloWorldWithException(); }
Example #8
Source File: CircuitBreakerTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void shouldInvokeRecoverFunction() { // tag::shouldInvokeRecoverFunction[] CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("testName"); // When I decorate my function and invoke the decorated function CheckedFunction0<String> checkedSupplier = circuitBreaker.decorateCheckedSupplier(() -> { throw new RuntimeException("BAM!"); }); 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"); // end::shouldInvokeRecoverFunction[] }
Example #9
Source File: Retry.java From resilience4j with Apache License 2.0 | 6 votes |
/** * Creates a retryable supplier. * * @param retry the retry context * @param supplier the original function * @param <T> the type of results supplied by this supplier * @return a retryable function */ static <T> CheckedFunction0<T> decorateCheckedSupplier(Retry retry, CheckedFunction0<T> supplier) { return () -> { Retry.Context<T> context = retry.context(); do { try { T result = supplier.apply(); final boolean validationOfResult = context.onResult(result); if (!validationOfResult) { context.onComplete(); return result; } } catch (Exception exception) { context.onError(exception); } } while (true); }; }
Example #10
Source File: BulkheadTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void shouldInvokeMap() { // tag::shouldInvokeMap[] Bulkhead bulkhead = Bulkhead.of("testName", config); // When I decorate my function CheckedFunction0<String> decoratedSupplier = Bulkhead.decorateCheckedSupplier(bulkhead, () -> "This can be any method which returns: 'Hello"); // and chain an other function with map Try<String> result = Try.of(decoratedSupplier) .map(value -> value + " world'"); // Then the Try Monad returns a Success<String>, if all functions ran successfully. assertThat(result.isSuccess()).isTrue(); assertThat(result.get()).isEqualTo("This can be any method which returns: 'Hello world'"); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(1); // end::shouldInvokeMap[] }
Example #11
Source File: BulkheadTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void shouldChainDecoratedFunctions() { // tag::shouldChainDecoratedFunctions[] Bulkhead bulkhead = Bulkhead.of("test", config); Bulkhead anotherBulkhead = Bulkhead.of("testAnother", config); // When I create a Supplier and a Function which are decorated by different Bulkheads CheckedFunction0<String> decoratedSupplier = Bulkhead.decorateCheckedSupplier(bulkhead, () -> "Hello"); CheckedFunction1<String, String> decoratedFunction = Bulkhead.decorateCheckedFunction(anotherBulkhead, (input) -> input + " world"); // and I chain a function with map Try<String> result = Try.of(decoratedSupplier) .mapTry(decoratedFunction); assertThat(result.isSuccess()).isTrue(); assertThat(result.get()).isEqualTo("Hello world"); assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(1); assertThat(anotherBulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(1); // end::shouldChainDecoratedFunctions[] }
Example #12
Source File: CircuitBreakerTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void shouldInvokeMap() { // tag::shouldInvokeMap[] CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("testName"); // When I decorate my function CheckedFunction0<String> decoratedSupplier = CircuitBreaker .decorateCheckedSupplier(circuitBreaker, () -> "This can be any method which returns: 'Hello"); // and chain an other function with map Try<String> result = Try.of(decoratedSupplier) .map(value -> value + " world'"); // Then the Try Monad returns a Success<String>, if all functions ran successfully. assertThat(result.isSuccess()).isTrue(); assertThat(result.get()).isEqualTo("This can be any method which returns: 'Hello world'"); // end::shouldInvokeMap[] }
Example #13
Source File: CircuitBreakerTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void shouldChainDecoratedFunctions() { // tag::shouldChainDecoratedFunctions[] CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("testName"); CircuitBreaker anotherCircuitBreaker = CircuitBreaker.ofDefaults("anotherTestName"); // When I create a Supplier and a Function which are decorated by different CircuitBreakers CheckedFunction0<String> decoratedSupplier = CircuitBreaker .decorateCheckedSupplier(circuitBreaker, () -> "Hello"); CheckedFunction1<String, String> decoratedFunction = CircuitBreaker .decorateCheckedFunction(anotherCircuitBreaker, (input) -> input + " world"); // and I chain a function with map Try<String> result = Try.of(decoratedSupplier) .mapTry(decoratedFunction); assertThat(result.isSuccess()).isTrue(); assertThat(result.get()).isEqualTo("Hello world"); // end::shouldChainDecoratedFunctions[] CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics(); assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(1); assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(0); CircuitBreaker.Metrics metrics2 = anotherCircuitBreaker.getMetrics(); assertThat(metrics2.getNumberOfBufferedCalls()).isEqualTo(1); assertThat(metrics2.getNumberOfFailedCalls()).isEqualTo(0); }
Example #14
Source File: DecoratorsTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void testDecorateCheckedSupplierWithFallback() throws Throwable { CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("helloBackend"); circuitBreaker.transitionToOpenState(); CheckedFunction0<String> checkedSupplier = Decorators .ofCheckedSupplier(() -> helloWorldService.returnHelloWorldWithException()) .withCircuitBreaker(circuitBreaker) .withFallback(CallNotPermittedException.class, e -> "Fallback") .decorate(); String result = checkedSupplier.apply(); assertThat(result).isEqualTo("Fallback"); CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics(); assertThat(metrics.getNumberOfNotPermittedCalls()).isEqualTo(1); then(helloWorldService).should(never()).returnHelloWorld(); }
Example #15
Source File: DecoratorsTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void testDecoratorBuilderWithRateLimiter() { given(helloWorldService.returnHelloWorld()).willReturn("Hello world"); RateLimiterConfig config = RateLimiterConfig.custom() .timeoutDuration(Duration.ofMillis(100)) .limitRefreshPeriod(Duration.ofSeconds(1)) .limitForPeriod(1) .build(); RateLimiter rateLimiter = RateLimiter.of("backendName", config); CheckedFunction0<String> restrictedSupplier = Decorators .ofCheckedSupplier(() -> helloWorldService.returnHelloWorld()) .withRateLimiter(rateLimiter) .decorate(); alignTime(rateLimiter); Try<String> firstTry = Try.of(restrictedSupplier); Try<String> secondTry = Try.of(restrictedSupplier); assertThat(firstTry.isSuccess()).isTrue(); assertThat(secondTry.isFailure()).isTrue(); assertThat(secondTry.getCause()).isInstanceOf(RequestNotPermitted.class); then(helloWorldService).should(times(1)).returnHelloWorld(); }
Example #16
Source File: CompletionStageFallbackDecorator.java From resilience4j with Apache License 2.0 | 6 votes |
@SuppressWarnings("unchecked") @Override public CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod, CheckedFunction0<Object> supplier) { return supplier.andThen(request -> { CompletionStage<Object> completionStage = (CompletionStage) request; CompletableFuture promise = new CompletableFuture(); completionStage.whenComplete((result, throwable) -> { if (throwable != null){ if (throwable instanceof CompletionException || throwable instanceof ExecutionException) { tryRecover(fallbackMethod, promise, throwable.getCause()); }else{ tryRecover(fallbackMethod, promise, throwable); } } else { promise.complete(result); } }); return promise; }); }
Example #17
Source File: CheckFunctionUtils.java From resilience4j with Apache License 2.0 | 6 votes |
/** * Returns a composed function that first executes the function and optionally recovers from an * exception. * * @param <T> return type of after * @param function the function which should be recovered from a certain exception * @param exceptionType the specific exception type that should be recovered * @param exceptionHandler the exception handler * @return a function composed of callable and exceptionHandler */ public static <X extends Throwable, T> CheckedFunction0<T> recover(CheckedFunction0<T> function, Class<X> exceptionType, CheckedFunction1<Throwable, T> exceptionHandler) { return () -> { try { return function.apply(); } catch (Throwable throwable) { if(exceptionType.isAssignableFrom(throwable.getClass())) { return exceptionHandler.apply(throwable); }else{ throw throwable; } } }; }
Example #18
Source File: CheckFunctionUtils.java From resilience4j with Apache License 2.0 | 6 votes |
/** * Returns a composed function that first executes the function and optionally recovers from an * exception. * * @param <T> return type of after * @param function the function which should be recovered from a certain exception * @param exceptionTypes the specific exception types that should be recovered * @param exceptionHandler the exception handler * @return a function composed of supplier and exceptionHandler */ public static <T> CheckedFunction0<T> recover(CheckedFunction0<T> function, List<Class<? extends Throwable>> exceptionTypes, CheckedFunction1<Throwable, T> exceptionHandler) { return () -> { try { return function.apply(); } catch (Exception exception) { if(exceptionTypes.stream().anyMatch(exceptionType -> exceptionType.isAssignableFrom(exception.getClass()))){ return exceptionHandler.apply(exception); }else{ throw exception; } } }; }
Example #19
Source File: ReactorFallbackDecorator.java From resilience4j with Apache License 2.0 | 6 votes |
@SuppressWarnings("unchecked") @Override public CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod, CheckedFunction0<Object> supplier) { return supplier.andThen(returnValue -> { if (Flux.class.isAssignableFrom(returnValue.getClass())) { Flux fluxReturnValue = (Flux) returnValue; return fluxReturnValue .onErrorResume(reactorOnErrorResume(fallbackMethod, Flux::error)); } else if (Mono.class.isAssignableFrom(returnValue.getClass())) { Mono monoReturnValue = (Mono) returnValue; return monoReturnValue .onErrorResume(reactorOnErrorResume(fallbackMethod, Mono::error)); } else { return returnValue; } }); }
Example #20
Source File: TimerTest.java From resilience4j with Apache License 2.0 | 6 votes |
@Test public void shouldDecorateCheckedSupplier() throws Throwable { given(helloWorldService.returnHelloWorldWithException()).willReturn("Hello world"); CheckedFunction0<String> timedSupplier = Timer .decorateCheckedSupplier(timer, helloWorldService::returnHelloWorldWithException); String value = timedSupplier.apply(); assertThat(timer.getMetrics().getNumberOfTotalCalls()).isEqualTo(1); assertThat(timer.getMetrics().getNumberOfSuccessfulCalls()).isEqualTo(1); assertThat(timer.getMetrics().getNumberOfFailedCalls()).isEqualTo(0); assertThat(metricRegistry.getCounters().size()).isEqualTo(2); assertThat(metricRegistry.getTimers().size()).isEqualTo(1); assertThat(value).isEqualTo("Hello world"); then(helloWorldService).should(times(1)).returnHelloWorldWithException(); }
Example #21
Source File: Lambdas.java From ts-reaktive with MIT License | 5 votes |
/** * Removes any thrown exceptions from the signature of the given lambda, while still throwing them. * Only safe when you can guarantee that the calling method actually declares the given checked exception. */ public static <T> io.vavr.Function0<T> unchecked(CheckedFunction0<T> f) { return () -> { try { return f.apply(); } catch (Throwable x) { throwSilently(x); return null; // code never reaches here }}; }
Example #22
Source File: BulkheadAspect.java From resilience4j with Apache License 2.0 | 5 votes |
private Object executeFallBack(ProceedingJoinPoint proceedingJoinPoint, String fallBackMethod, Method method, CheckedFunction0<Object> bulkhead) throws Throwable { FallbackMethod fallbackMethod = FallbackMethod .create(fallBackMethod, method, proceedingJoinPoint.getArgs(), proceedingJoinPoint.getTarget()); return fallbackDecorators.decorate(fallbackMethod, bulkhead).apply(); }
Example #23
Source File: DefaultFallbackDecorator.java From resilience4j with Apache License 2.0 | 5 votes |
@Override public CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod, CheckedFunction0<Object> supplier) { return () -> { try { return supplier.apply(); } catch (IllegalReturnTypeException e) { throw e; } catch (Throwable throwable) { return fallbackMethod.fallback(throwable); } }; }
Example #24
Source File: RxJava2FallbackDecorator.java From resilience4j with Apache License 2.0 | 5 votes |
@Override public CheckedFunction0<Object> decorate(FallbackMethod fallbackMethod, CheckedFunction0<Object> supplier) { return supplier.andThen(request -> { if (request instanceof ObservableSource) { Observable<?> observable = (Observable<?>) request; return observable .onErrorResumeNext(rxJava2OnErrorResumeNext(fallbackMethod, Observable::error)); } else if (request instanceof SingleSource) { Single<?> single = (Single) request; return single .onErrorResumeNext(rxJava2OnErrorResumeNext(fallbackMethod, Single::error)); } else if (request instanceof CompletableSource) { Completable completable = (Completable) request; return completable.onErrorResumeNext( rxJava2OnErrorResumeNext(fallbackMethod, Completable::error)); } else if (request instanceof MaybeSource) { Maybe<?> maybe = (Maybe) request; return maybe .onErrorResumeNext(rxJava2OnErrorResumeNext(fallbackMethod, Maybe::error)); } else if (request instanceof Flowable) { Flowable<?> flowable = (Flowable) request; return flowable .onErrorResumeNext(rxJava2OnErrorResumeNext(fallbackMethod, Flowable::error)); } else { return request; } }); }
Example #25
Source File: CallMeter.java From resilience4j with Apache License 2.0 | 5 votes |
/** * Creates a timed checked supplier. * * @param meter the call meter to use * @param supplier the original supplier * @return a timed supplier */ static <T> CheckedFunction0<T> decorateCheckedSupplier(CallMeterBase meter, CheckedFunction0<T> supplier) { return () -> { final Timer timer = meter.startTimer(); try { final T returnValue = supplier.apply(); timer.onSuccess(); return returnValue; } catch (Throwable e) { timer.onError(); throw e; } }; }
Example #26
Source File: RetrofitRateLimiter.java From resilience4j with Apache License 2.0 | 5 votes |
@Override public Response<T> execute() throws IOException { CheckedFunction0<Response<T>> restrictedSupplier = RateLimiter .decorateCheckedSupplier(rateLimiter, call::execute); final Try<Response<T>> response = Try.of(restrictedSupplier); return response.isSuccess() ? response.get() : handleFailure(response); }
Example #27
Source File: Timer.java From resilience4j with Apache License 2.0 | 5 votes |
/** * Creates a timed checked supplier. * * @param timer the timer to use * @param supplier the original supplier * @return a timed supplier */ static <T> CheckedFunction0<T> decorateCheckedSupplier(Timer timer, CheckedFunction0<T> supplier) { return () -> { final Timer.Context context = timer.context(); try { T returnValue = supplier.apply(); context.onSuccess(); return returnValue; } catch (Throwable e) { context.onError(); throw e; } }; }
Example #28
Source File: CheckFunctionUtilsTest.java From resilience4j with Apache License 2.0 | 5 votes |
@Test public void shouldRecoverFromException() throws Throwable { CheckedFunction0<String> callable = () -> { throw new IOException("BAM!"); }; CheckedFunction0<String> callableWithRecovery = CheckFunctionUtils.recover(callable, (ex) -> "Bla"); String result = callableWithRecovery.apply(); assertThat(result).isEqualTo("Bla"); }
Example #29
Source File: CheckFunctionUtilsTest.java From resilience4j with Apache License 2.0 | 5 votes |
@Test(expected = RuntimeException.class) public void shouldRethrowException2() throws Throwable { CheckedFunction0<String> callable = () -> { throw new RuntimeException("BAM!"); }; CheckedFunction0<String> callableWithRecovery = CheckFunctionUtils.recover(callable, IllegalArgumentException.class, (ex) -> "Bla"); callableWithRecovery.apply(); }
Example #30
Source File: Bulkhead.java From resilience4j with Apache License 2.0 | 5 votes |
/** * Returns a supplier which is decorated by a bulkhead. * * @param bulkhead the Bulkhead * @param supplier the original supplier * @param <T> the type of results supplied by this supplier * @return a supplier which is decorated by a Bulkhead. */ static <T> CheckedFunction0<T> decorateCheckedSupplier(Bulkhead bulkhead, CheckedFunction0<T> supplier) { return () -> { bulkhead.acquirePermission(); try { return supplier.apply(); } finally { bulkhead.onComplete(); } }; }