Search in sources :

Example 11 with RateLimiterConfig

use of io.github.resilience4j.ratelimiter.RateLimiterConfig in project resilience4j by resilience4j.

the class DecoratorsTest method testDecoratorBuilderWithRateLimiter.

@Test
public void testDecoratorBuilderWithRateLimiter() {
    // Given the HelloWorldService returns Hello world
    given(helloWorldService.returnHelloWorld()).willReturn("Hello world");
    // Create a custom RateLimiter configuration
    RateLimiterConfig config = RateLimiterConfig.custom().timeoutDuration(Duration.ofMillis(100)).limitRefreshPeriod(Duration.ofSeconds(1)).limitForPeriod(1).build();
    // Create a RateLimiter
    RateLimiter rateLimiter = RateLimiter.of("backendName", config);
    CheckedFunction0<String> restrictedSupplier = Decorators.ofCheckedSupplier(() -> helloWorldService.returnHelloWorld()).withRateLimiter(rateLimiter).decorate();
    alignTime(rateLimiter);
    Try<String> firstTry = Try.of(restrictedSupplier);
    assertThat(firstTry.isSuccess()).isTrue();
    Try<String> secondTry = Try.of(restrictedSupplier);
    assertThat(secondTry.isFailure()).isTrue();
    assertThat(secondTry.getCause()).isInstanceOf(RequestNotPermitted.class);
    // Then the helloWorldService should be invoked 1 time
    BDDMockito.then(helloWorldService).should(times(1)).returnHelloWorld();
}
Also used : RateLimiterConfig(io.github.resilience4j.ratelimiter.RateLimiterConfig) RateLimiter(io.github.resilience4j.ratelimiter.RateLimiter) Test(org.junit.Test)

Example 12 with RateLimiterConfig

use of io.github.resilience4j.ratelimiter.RateLimiterConfig in project resilience4j by resilience4j.

the class RateLimiterHealthIndicatorTest method health.

@Test
public void health() throws Exception {
    // given
    RateLimiterConfig config = mock(RateLimiterConfig.class);
    AtomicRateLimiter.AtomicRateLimiterMetrics metrics = mock(AtomicRateLimiter.AtomicRateLimiterMetrics.class);
    AtomicRateLimiter rateLimiter = mock(AtomicRateLimiter.class);
    // when
    when(rateLimiter.getRateLimiterConfig()).thenReturn(config);
    when(rateLimiter.getMetrics()).thenReturn(metrics);
    when(rateLimiter.getDetailedMetrics()).thenReturn(metrics);
    when(config.getTimeoutDuration()).thenReturn(Duration.ofNanos(30L));
    when(metrics.getAvailablePermissions()).thenReturn(5, -1, -2);
    when(metrics.getNumberOfWaitingThreads()).thenReturn(0, 1, 2);
    when(metrics.getNanosToWait()).thenReturn(20L, 40L);
    // then
    RateLimiterHealthIndicator healthIndicator = new RateLimiterHealthIndicator(rateLimiter);
    Health health = healthIndicator.health();
    then(health.getStatus()).isEqualTo(Status.UP);
    health = healthIndicator.health();
    then(health.getStatus()).isEqualTo(Status.UNKNOWN);
    health = healthIndicator.health();
    then(health.getStatus()).isEqualTo(Status.DOWN);
    then(health.getDetails()).contains(entry("availablePermissions", -2), entry("numberOfWaitingThreads", 2));
}
Also used : Health(org.springframework.boot.actuate.health.Health) RateLimiterConfig(io.github.resilience4j.ratelimiter.RateLimiterConfig) AtomicRateLimiter(io.github.resilience4j.ratelimiter.internal.AtomicRateLimiter) Test(org.junit.Test)

Example 13 with RateLimiterConfig

use of io.github.resilience4j.ratelimiter.RateLimiterConfig in project resilience4j by resilience4j.

the class RateLimiterMethodInterceptor method handleProceedWithException.

private Object handleProceedWithException(MethodInvocation invocation, io.github.resilience4j.ratelimiter.RateLimiter rateLimiter, RecoveryFunction<?> recoveryFunction) throws Throwable {
    RateLimiterConfig rateLimiterConfig = rateLimiter.getRateLimiterConfig();
    Duration timeoutDuration = rateLimiterConfig.getTimeoutDuration();
    boolean permission = rateLimiter.getPermission(timeoutDuration);
    if (Thread.interrupted()) {
        throw new IllegalStateException("Thread was interrupted during permission wait");
    }
    if (!permission) {
        Throwable t = new RequestNotPermitted("Request not permitted for limiter: " + rateLimiter.getName());
        return recoveryFunction.apply(t);
    }
    return invocation.proceed();
}
Also used : RequestNotPermitted(io.github.resilience4j.ratelimiter.RequestNotPermitted) RateLimiterConfig(io.github.resilience4j.ratelimiter.RateLimiterConfig) Duration(java.time.Duration)

Example 14 with RateLimiterConfig

use of io.github.resilience4j.ratelimiter.RateLimiterConfig in project resilience4j by resilience4j.

the class RateLimiterMethodInterceptor method invoke.

@SuppressWarnings("unchecked")
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
    RateLimiter annotation = invocation.getMethod().getAnnotation(RateLimiter.class);
    RecoveryFunction<?> recoveryFunction = annotation.recovery().newInstance();
    if (registry == null) {
        registry = RateLimiterRegistry.ofDefaults();
    }
    io.github.resilience4j.ratelimiter.RateLimiter rateLimiter = registry.rateLimiter(annotation.name());
    if (rateLimiter == null) {
        return invocation.proceed();
    }
    Class<?> returnType = invocation.getMethod().getReturnType();
    if (Promise.class.isAssignableFrom(returnType)) {
        Promise<?> result = (Promise<?>) proceed(invocation, rateLimiter, recoveryFunction);
        if (result != null) {
            RateLimiterTransformer transformer = RateLimiterTransformer.of(rateLimiter).recover(recoveryFunction);
            result = result.transform(transformer);
        }
        return result;
    } else if (Observable.class.isAssignableFrom(returnType)) {
        Observable<?> result = (Observable<?>) proceed(invocation, rateLimiter, recoveryFunction);
        if (result != null) {
            RateLimiterOperator operator = RateLimiterOperator.of(rateLimiter);
            result = result.lift(operator).onErrorReturn(t -> recoveryFunction.apply((Throwable) t));
        }
        return result;
    } else if (Flowable.class.isAssignableFrom(returnType)) {
        Flowable<?> result = (Flowable<?>) proceed(invocation, rateLimiter, recoveryFunction);
        if (result != null) {
            RateLimiterOperator operator = RateLimiterOperator.of(rateLimiter);
            result = result.lift(operator).onErrorReturn(t -> recoveryFunction.apply((Throwable) t));
        }
        return result;
    } else if (Single.class.isAssignableFrom(returnType)) {
        Single<?> result = (Single<?>) proceed(invocation, rateLimiter, recoveryFunction);
        if (result != null) {
            RateLimiterOperator operator = RateLimiterOperator.of(rateLimiter);
            result = result.lift(operator).onErrorReturn(t -> recoveryFunction.apply((Throwable) t));
        }
        return result;
    } else if (CompletionStage.class.isAssignableFrom(returnType)) {
        RateLimiterConfig rateLimiterConfig = rateLimiter.getRateLimiterConfig();
        Duration timeoutDuration = rateLimiterConfig.getTimeoutDuration();
        if (rateLimiter.getPermission(timeoutDuration)) {
            return proceed(invocation, rateLimiter, recoveryFunction);
        } else {
            final CompletableFuture promise = new CompletableFuture<>();
            Throwable t = new RequestNotPermitted("Request not permitted for limiter: " + rateLimiter.getName());
            try {
                promise.complete(recoveryFunction.apply(t));
            } catch (Throwable t2) {
                promise.completeExceptionally(t2);
            }
            return promise;
        }
    }
    return handleProceedWithException(invocation, rateLimiter, recoveryFunction);
}
Also used : Inject(com.google.inject.Inject) RateLimiterOperator(io.github.resilience4j.ratelimiter.operator.RateLimiterOperator) Promise(ratpack.exec.Promise) CompletableFuture(java.util.concurrent.CompletableFuture) RequestNotPermitted(io.github.resilience4j.ratelimiter.RequestNotPermitted) Single(io.reactivex.Single) RecoveryFunction(io.github.resilience4j.ratpack.recovery.RecoveryFunction) MethodInterceptor(org.aopalliance.intercept.MethodInterceptor) MethodInvocation(org.aopalliance.intercept.MethodInvocation) CompletionStage(java.util.concurrent.CompletionStage) Flowable(io.reactivex.Flowable) Duration(java.time.Duration) Observable(io.reactivex.Observable) RateLimiterConfig(io.github.resilience4j.ratelimiter.RateLimiterConfig) RateLimiterRegistry(io.github.resilience4j.ratelimiter.RateLimiterRegistry) RateLimiterConfig(io.github.resilience4j.ratelimiter.RateLimiterConfig) Duration(java.time.Duration) Observable(io.reactivex.Observable) Promise(ratpack.exec.Promise) CompletableFuture(java.util.concurrent.CompletableFuture) RequestNotPermitted(io.github.resilience4j.ratelimiter.RequestNotPermitted) RateLimiterOperator(io.github.resilience4j.ratelimiter.operator.RateLimiterOperator) Single(io.reactivex.Single) Flowable(io.reactivex.Flowable)

Example 15 with RateLimiterConfig

use of io.github.resilience4j.ratelimiter.RateLimiterConfig in project resilience4j by resilience4j.

the class SemaphoreBasedRateLimiter method changeTimeoutDuration.

/**
 * {@inheritDoc}
 */
@Override
public void changeTimeoutDuration(Duration timeoutDuration) {
    RateLimiterConfig newConfig = RateLimiterConfig.from(rateLimiterConfig.get()).timeoutDuration(timeoutDuration).build();
    rateLimiterConfig.set(newConfig);
}
Also used : RateLimiterConfig(io.github.resilience4j.ratelimiter.RateLimiterConfig)

Aggregations

RateLimiterConfig (io.github.resilience4j.ratelimiter.RateLimiterConfig)20 Test (org.junit.Test)12 RateLimiter (io.github.resilience4j.ratelimiter.RateLimiter)5 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)5 RateLimiterRegistry (io.github.resilience4j.ratelimiter.RateLimiterRegistry)4 RequestNotPermitted (io.github.resilience4j.ratelimiter.RequestNotPermitted)2 Duration (java.time.Duration)2 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)2 Inject (com.google.inject.Inject)1 AtomicRateLimiter (io.github.resilience4j.ratelimiter.internal.AtomicRateLimiter)1 RateLimiterOperator (io.github.resilience4j.ratelimiter.operator.RateLimiterOperator)1 RecoveryFunction (io.github.resilience4j.ratpack.recovery.RecoveryFunction)1 Flowable (io.reactivex.Flowable)1 Observable (io.reactivex.Observable)1 Single (io.reactivex.Single)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 CompletionStage (java.util.concurrent.CompletionStage)1 SynchronousQueue (java.util.concurrent.SynchronousQueue)1 MethodInterceptor (org.aopalliance.intercept.MethodInterceptor)1 MethodInvocation (org.aopalliance.intercept.MethodInvocation)1