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();
}
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));
}
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();
}
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);
}
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);
}
Aggregations