Java源码示例:io.github.resilience4j.timelimiter.TimeLimiter

示例1
private TimeLimiterCoalition createTimeLimiter(String ruleName, CircuitBreakerRule rule) {
    if (rule == null) {
        return null;
    }
    Duration timeout = rule.getTimeoutDuration();
    if (rule.getEnabled() != null && rule.getEnabled() &&
            timeout != null && !timeout.isNegative() && !timeout.isZero()) {
        try {
            TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
                    .timeoutDuration(rule.getTimeoutDuration())
                    .cancelRunningFuture(rule.getCancelRunningFuture())
                    .build();
            TimeLimiter timeLimiter = TimeLimiter.of(timeLimiterConfig);
            TimeLimiterCoalition timeLimiterCoalition = new TimeLimiterCoalition(
                    timeLimiter, rule);
            return timeLimiterCoalition;
        } catch (Exception e) {
            logger.error("failed to create timeLimiter,name:{},id{}",
                    ruleName, rule.getRuleId(), e);
            return null;
        }
    }
    return null;
}
 
示例2
@Before
public void init() {
    TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
            .timeoutDuration(Duration.ofSeconds(1))
            .cancelRunningFuture(true)
            .build();
     timeLimiter = TimeLimiter.of(timeLimiterConfig);

    CustomizableThreadFactory factory = new CustomizableThreadFactory("timeLimiter-");
    factory.setDaemon(true);
    executorService = Executors.newCachedThreadPool(factory);

    CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig
            .custom()
            .enableAutomaticTransitionFromOpenToHalfOpen()
            .failureRateThreshold(50)
            .ringBufferSizeInClosedState(10)
            .ringBufferSizeInHalfOpenState(2)
            .build();

    circuitBreaker = CircuitBreaker.of("backendName", circuitBreakerConfig);
}
 
示例3
@Test
public void testTimeout() throws Throwable {
    Callable<Object> callable = () -> {
        Thread.sleep(10000);
        return null;
    };
    Supplier<Future<Object>> supplier = () -> executorService.submit(callable);
    // Wrap your call to BackendService.doSomething() in a future provided by your executor
    Callable<Object> result = TimeLimiter.decorateFutureSupplier(timeLimiter, supplier);
    long start = System.currentTimeMillis();
    try {
        result.call();
        fail("fail");
    } catch (Throwable t) {
        long cost = System.currentTimeMillis() - start;
        assertThat(cost, Matchers.lessThan(1010L));
        assertThat(t, Matchers.instanceOf(TimeoutException.class));
    }
}
 
示例4
@Override
public void publishMetrics(TimeLimiter timeLimiter) {

    String name = timeLimiter.getName();
    String successfulName = name(prefix, name, SUCCESSFUL);
    String failedName = name(prefix, name, FAILED);
    String timeoutName = name(prefix, name, TIMEOUT);

    Counter successes = metricRegistry.counter(successfulName);
    Counter failures = metricRegistry.counter(failedName);
    Counter timeouts = metricRegistry.counter(timeoutName);

    timeLimiter.getEventPublisher().onSuccess(event -> successes.inc());
    timeLimiter.getEventPublisher().onError(event -> failures.inc());
    timeLimiter.getEventPublisher().onTimeout(event -> timeouts.inc());

    List<String> metricNames = Arrays.asList(successfulName, failedName, timeoutName);
    metricsNameMap.put(name, new HashSet<>(metricNames));
}
 
示例5
/**
 * This method returns a desired Tax(taxAmount, taxPercentage) value when the TaxService is up. 
 * If the TaxService is down, it applies a combination of following fault tolerance patterns 
 * in a sequence: TimeLimiter, CircuitBreaker and Retry using a Callable. When all the attempts 
 * are exhausted it calls a fallback method to recover from failure and offers the default tax value.
 * 
 * @param amount
 * @return
 */
public Tax applyResiliencePatterns(BigDecimal amount) {

	CircuitBreaker circuitBreaker = configureCircuitBreaker();
	TimeLimiter timeLimiter = configureTimeLimiter();
	Retry retry = configureRetry();
	
	Supplier<CompletableFuture<Tax>> futureSupplier = () -> CompletableFuture.supplyAsync(() -> salesOrderService.supplyTax(amount));
	Callable<Tax> callable = TimeLimiter.decorateFutureSupplier(timeLimiter, futureSupplier);
	callable = CircuitBreaker.decorateCallable(circuitBreaker, callable);
	callable = Retry.decorateCallable(retry, callable);
	
	//Executing the decorated callable and recovering from any exception by calling the fallback method
	Try<Tax> result = Try.ofCallable(callable).recover(throwable -> taxServiceFallback(amount));
	return result.get();
}
 
示例6
private TimeLimiterMetrics(String prefix, Iterable<TimeLimiter> timeLimiters,
    MetricRegistry metricRegistry) {
    requireNonNull(prefix, PREFIX_NULL);
    requireNonNull(timeLimiters, ITERABLE_NULL);
    requireNonNull(metricRegistry);
    this.metricRegistry = metricRegistry;
    timeLimiters.forEach(timeLimiter -> {
            String name = timeLimiter.getName();
            Counter successes = metricRegistry.counter(name(prefix, name, SUCCESSFUL));
            Counter failures = metricRegistry.counter(name(prefix, name, FAILED));
            Counter timeouts = metricRegistry.counter(name(prefix, name, TIMEOUT));
            timeLimiter.getEventPublisher().onSuccess(event -> successes.inc());
            timeLimiter.getEventPublisher().onError(event -> failures.inc());
            timeLimiter.getEventPublisher().onTimeout(event -> timeouts.inc());
        }
    );
}
 
示例7
@Test
public void shouldThrowTimeoutExceptionWithCompletionStage() throws Exception {
    Duration timeoutDuration = Duration.ofMillis(300);
    TimeLimiter timeLimiter = TimeLimiter.of(timeoutDuration);
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    Supplier<CompletionStage<Integer>> supplier = () -> CompletableFuture.supplyAsync(() -> {
        try {
            // sleep for timeout.
            Thread.sleep(500);
        } catch (InterruptedException e) {
            // nothing
        }
        return 0;
    });

    CompletionStage<Integer> decorated = TimeLimiter
        .decorateCompletionStage(timeLimiter, scheduler, supplier).get();
    Try<Integer> decoratedResult = Try.ofCallable(() -> decorated.toCompletableFuture().get());
    assertThat(decoratedResult.isFailure()).isTrue();
    assertThat(decoratedResult.getCause()).isInstanceOf(ExecutionException.class)
        .hasCauseExactlyInstanceOf(TimeoutException.class);
}
 
示例8
@Test
public void shouldThrowTimeoutExceptionAndNotInvokeCancel() throws Exception {
    Duration timeoutDuration = Duration.ofSeconds(1);
    TimeLimiter timeLimiter = TimeLimiter
        .of(TimeLimiterConfig.custom().timeoutDuration(timeoutDuration)
            .cancelRunningFuture(false).build());

    @SuppressWarnings("unchecked")
    Future<Integer> mockFuture = (Future<Integer>) mock(Future.class);

    Supplier<Future<Integer>> supplier = () -> mockFuture;
    given(mockFuture.get(timeoutDuration.toMillis(), TimeUnit.MILLISECONDS))
        .willThrow(new TimeoutException());

    Callable<Integer> decorated = TimeLimiter.decorateFutureSupplier(timeLimiter, supplier);
    Try<Integer> decoratedResult = Try.ofCallable(decorated);

    assertThat(decoratedResult.isFailure()).isTrue();
    assertThat(decoratedResult.getCause()).isInstanceOf(TimeoutException.class);

    then(mockFuture).should(never()).cancel(true);
}
 
示例9
@Test
public void shouldReturnResult() throws Exception {
    Duration timeoutDuration = Duration.ofSeconds(1);
    TimeLimiter timeLimiter = TimeLimiter.of(timeoutDuration);

    @SuppressWarnings("unchecked")
    Future<Integer> mockFuture = (Future<Integer>) mock(Future.class);

    Supplier<Future<Integer>> supplier = () -> mockFuture;
    given(mockFuture.get(timeoutDuration.toMillis(), TimeUnit.MILLISECONDS)).willReturn(42);

    int result = timeLimiter.executeFutureSupplier(supplier);
    assertThat(result).isEqualTo(42);

    int result2 = timeLimiter.decorateFutureSupplier(supplier).call();
    assertThat(result2).isEqualTo(42);
}
 
示例10
@Test
public void shouldReturnResultWithCompletionStage() throws Exception {
    Duration timeoutDuration = Duration.ofSeconds(1);
    TimeLimiter timeLimiter = TimeLimiter.of(timeoutDuration);
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

    Supplier<CompletionStage<Integer>> supplier = () -> CompletableFuture.supplyAsync(() -> {
        try {
            // sleep but not timeout.
            Thread.sleep(500);
        } catch (InterruptedException e) {
            // nothing
        }
        return 42;
    });

    int result = timeLimiter.executeCompletionStage(scheduler, supplier).toCompletableFuture()
        .get();
    assertThat(result).isEqualTo(42);

    int result2 = timeLimiter.decorateCompletionStage(scheduler, supplier).get()
        .toCompletableFuture().get();
    assertThat(result2).isEqualTo(42);
}
 
示例11
@Test
public void shouldRegisterMetrics() throws Exception {
    TimeLimiter timeLimiter = given(metricRegistry);
    String expectedPrefix = "resilience4j.timelimiter.testLimit.";
    Supplier<CompletableFuture<String>> futureSupplier = () ->
        CompletableFuture.completedFuture("Hello world");

    String result = timeLimiter.decorateFutureSupplier(futureSupplier).call();

    then(result).isEqualTo("Hello world");
    assertThat(metricRegistry).hasMetricsSize(3);
    assertThat(metricRegistry).counter(expectedPrefix + SUCCESSFUL)
        .hasValue(1L);
    assertThat(metricRegistry).counter(expectedPrefix + FAILED)
        .hasValue(0L);
    assertThat(metricRegistry).counter(expectedPrefix + TIMEOUT)
        .hasValue(0L);
}
 
示例12
@Test
@SuppressWarnings("unchecked")
public void timeLimiterPositiveWithSupplier() {
    TimeLimiterRegistry registry = new InMemoryTimeLimiterRegistry(config);
    Supplier<TimeLimiterConfig> timeLimiterConfigSupplier = mock(Supplier.class);
    given(timeLimiterConfigSupplier.get()).willReturn(config);

    TimeLimiter firstTimeLimiter = registry.timeLimiter("test", timeLimiterConfigSupplier);
    verify(timeLimiterConfigSupplier, times(1)).get();
    TimeLimiter sameAsFirst = registry.timeLimiter("test", timeLimiterConfigSupplier);
    verify(timeLimiterConfigSupplier, times(1)).get();
    TimeLimiter anotherLimit = registry.timeLimiter("test1", timeLimiterConfigSupplier);
    verify(timeLimiterConfigSupplier, times(2)).get();

    then(firstTimeLimiter).isEqualTo(sameAsFirst);
    then(firstTimeLimiter).isNotEqualTo(anotherLimit);
}
 
示例13
@Test
public void shouldRecordErrors() {
    TimeLimiter timeLimiter = TimeLimiter.of(TimeLimiterConfig.ofDefaults());
    metricRegistry.registerAll(TimeLimiterMetrics.ofTimeLimiter(timeLimiter));

    timeLimiter.onError(new RuntimeException());
    timeLimiter.onError(new RuntimeException());

    assertThat(metricRegistry).hasMetricsSize(3);
    assertThat(metricRegistry).counter(DEFAULT_PREFIX + SUCCESSFUL)
        .hasValue(0L);
    assertThat(metricRegistry).counter(DEFAULT_PREFIX + FAILED)
        .hasValue(2L);
    assertThat(metricRegistry).counter(DEFAULT_PREFIX + TIMEOUT)
        .hasValue(0L);
}
 
示例14
@Test
public void shouldThrowTimeoutException() {
    TimeLimiter timeLimiter = TimeLimiter.of("helloBackend", TimeLimiterConfig.custom()
        .timeoutDuration(Duration.ofMillis(100)).build());
    CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("helloBackend");
    ThreadPoolBulkhead bulkhead = ThreadPoolBulkhead.ofDefaults("helloBackend");
    CompletionStage<String> completionStage = Decorators
        .ofCallable(() -> {
            Thread.sleep(1000);
            return "Bla";
        })
        .withThreadPoolBulkhead(bulkhead)
        .withTimeLimiter(timeLimiter, Executors.newSingleThreadScheduledExecutor())
        .withCircuitBreaker(circuitBreaker)
        .get();

    assertThatThrownBy(() -> completionStage.toCompletableFuture().get())
        .hasCauseInstanceOf(TimeoutException.class);

    CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics();
    assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(1);
    assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(1);
}
 
示例15
@Test
public void testDecorateSupplierWithThreadPoolBulkhead()
    throws ExecutionException, InterruptedException {

    given(helloWorldService.returnHelloWorld()).willReturn("Hello world");
    CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("helloBackend");

    CompletableFuture<String> future = Decorators
        .ofSupplier(() -> helloWorldService.returnHelloWorld())
        .withThreadPoolBulkhead(ThreadPoolBulkhead.ofDefaults("helloBackend"))
        .withTimeLimiter(TimeLimiter.ofDefaults(), Executors.newSingleThreadScheduledExecutor())
        .withCircuitBreaker(circuitBreaker)
        .get().toCompletableFuture();

    String result = future.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)).returnHelloWorld();
}
 
示例16
@Test
public void shouldRecordTimeouts() {
    TimeLimiter timeLimiter = TimeLimiter.of(TimeLimiterConfig.custom()
        .timeoutDuration(Duration.ZERO)
        .build());
    metricRegistry.registerAll(TimeLimiterMetrics.ofTimeLimiter(timeLimiter));

    timeLimiter.onError(new TimeoutException());
    timeLimiter.onError(new TimeoutException());

    assertThat(metricRegistry).hasMetricsSize(3);
    assertThat(metricRegistry).counter(DEFAULT_PREFIX + SUCCESSFUL)
        .hasValue(0L);
    assertThat(metricRegistry).counter(DEFAULT_PREFIX + FAILED)
        .hasValue(0L);
    assertThat(metricRegistry).counter(DEFAULT_PREFIX + TIMEOUT)
        .hasValue(2L);
}
 
示例17
public InMemoryTimeLimiterRegistry(Map<String, TimeLimiterConfig> configs,
    RegistryEventConsumer<TimeLimiter> registryEventConsumer,
    io.vavr.collection.Map<String, String> tags) {
    this(configs.getOrDefault(DEFAULT_CONFIG, TimeLimiterConfig.ofDefaults()), registryEventConsumer,
        tags);
    this.configurations.putAll(configs);
}
 
示例18
public InMemoryTimeLimiterRegistry(Map<String, TimeLimiterConfig> configs,
    List<RegistryEventConsumer<TimeLimiter>> registryEventConsumers,
    io.vavr.collection.Map<String, String> tags) {
    this(configs.getOrDefault(DEFAULT_CONFIG, TimeLimiterConfig.ofDefaults()),
        registryEventConsumers, tags);
    this.configurations.putAll(configs);
}
 
示例19
@Override
public TimeLimiter timeLimiter(String name,
    TimeLimiterConfig timeLimiterConfig,
    io.vavr.collection.Map<String, String> tags) {
    return computeIfAbsent(name, () -> TimeLimiter.of(name,
        Objects.requireNonNull(timeLimiterConfig, CONFIG_MUST_NOT_BE_NULL), getAllTags(tags)));
}
 
示例20
@Override
public TimeLimiter timeLimiter(String name, String configName,
    io.vavr.collection.Map<String, String> tags) {
    TimeLimiterConfig config = getConfiguration(configName)
        .orElseThrow(() -> new ConfigurationNotFoundException(configName));
    return timeLimiter(name, config, tags);
}
 
示例21
@Test
public void shouldReturnCorrectTimeoutDuration() {
    Duration timeoutDuration = Duration.ofSeconds(1);
    TimeLimiter timeLimiter = TimeLimiter.of(timeoutDuration);
    assertThat(timeLimiter).isNotNull();
    assertThat(timeLimiter.getTimeLimiterConfig().getTimeoutDuration())
        .isEqualTo(timeoutDuration);
}
 
示例22
@Test
public void unwrapExecutionException() {
    TimeLimiter timeLimiter = TimeLimiter.ofDefaults();
    ExecutorService executorService = Executors.newSingleThreadExecutor();

    Supplier<Future<Integer>> supplier = () -> executorService.submit(() -> {
        throw new RuntimeException();
    });
    Callable<Integer> decorated = TimeLimiter.decorateFutureSupplier(timeLimiter, supplier);

    Try<Integer> decoratedResult = Try.ofCallable(decorated);

    assertThat(decoratedResult.getCause() instanceof RuntimeException).isTrue();
}
 
示例23
@Override
protected TimeLimiter given(MetricRegistry metricRegistry) {
    TimeLimiterRegistry timeLimiterRegistry = TimeLimiterRegistry.ofDefaults();
    TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter("testLimit");
    metricRegistry.registerAll(TimeLimiterMetrics.ofTimeLimiterRegistry(timeLimiterRegistry));

    return timeLimiter;
}
 
示例24
@Override
public void publishMetrics(TimeLimiter entry) {
    String name = entry.getName();
    entry.getEventPublisher()
        .onSuccess(event -> callsCounter.labels(name, KIND_SUCCESSFUL).inc())
        .onError(event -> callsCounter.labels(name, KIND_FAILED).inc())
        .onTimeout(event -> callsCounter.labels(name, KIND_TIMEOUT).inc());
}
 
示例25
@Override
protected TimeLimiter given(String prefix, MetricRegistry metricRegistry) {
    TimeLimiterRegistry timeLimiterRegistry = TimeLimiterRegistry.ofDefaults();
    TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter("testLimit");
    metricRegistry
        .registerAll(TimeLimiterMetrics.ofTimeLimiterRegistry(prefix, timeLimiterRegistry));

    return timeLimiter;
}
 
示例26
@Test
public void customMetricNamesOverrideDefaultOnes() {
    TimeLimiterMetricsPublisher.MetricNames names = TimeLimiterMetricsPublisher.MetricNames
        .custom()
        .callsMetricName("custom_calls")
        .build();
    CollectorRegistry customRegistry = new CollectorRegistry();
    TimeLimiterMetricsPublisher timeLimiterMetricsPublisher = new TimeLimiterMetricsPublisher(
        names);
    timeLimiterMetricsPublisher.register(customRegistry);

    TimeLimiterRegistry timeLimiterRegistry = TimeLimiterRegistry
        .of(TimeLimiterConfig.ofDefaults(), timeLimiterMetricsPublisher);
    TimeLimiter timeLimiter = timeLimiterRegistry.timeLimiter("backendA");

    timeLimiter.onSuccess();
    timeLimiter.onError(new RuntimeException());
    timeLimiter.onError(new TimeoutException());

    Double successfulCalls = getSampleValue(customRegistry, "custom_calls", KIND_SUCCESSFUL);
    Double failedCalls = getSampleValue(customRegistry, "custom_calls", KIND_FAILED);
    Double timeoutCalls = getSampleValue(customRegistry, "custom_calls", KIND_TIMEOUT);

    assertThat(successfulCalls).isNotNull();
    assertThat(failedCalls).isNotNull();
    assertThat(timeoutCalls).isNotNull();
}
 
示例27
@Override
public void bindTo(MeterRegistry registry) {
    for (TimeLimiter timeLimiter : timeLimiterRegistry.getAllTimeLimiters()) {
        addMetrics(registry, timeLimiter);
    }
    timeLimiterRegistry.getEventPublisher()
        .onEntryAdded(event -> addMetrics(registry, event.getAddedEntry()));
    timeLimiterRegistry.getEventPublisher()
        .onEntryRemoved(event -> removeMetrics(registry, event.getRemovedEntry().getName()));
    timeLimiterRegistry.getEventPublisher().onEntryReplaced(event -> {
        removeMetrics(registry, event.getOldEntry().getName());
        addMetrics(registry, event.getNewEntry());
    });
}
 
示例28
protected void registerMetrics(MeterRegistry meterRegistry, TimeLimiter timeLimiter, List<Tag> customTags) {
    // Remove previous meters before register
    removeMetrics(meterRegistry, timeLimiter.getName());

    Counter successes = Counter.builder(names.getCallsMetricName())
        .description("The number of successful calls")
        .tag(TagNames.NAME, timeLimiter.getName())
        .tag(TagNames.KIND, KIND_SUCCESSFUL)
        .tags(customTags)
        .register(meterRegistry);
    Counter failures = Counter.builder(names.getCallsMetricName())
        .description("The number of failed calls")
        .tag(TagNames.NAME, timeLimiter.getName())
        .tag(TagNames.KIND, KIND_FAILED)
        .tags(customTags)
        .register(meterRegistry);
    Counter timeouts = Counter.builder(names.getCallsMetricName())
        .description("The number of timed out calls")
        .tag(TagNames.NAME, timeLimiter.getName())
        .tag(TagNames.KIND, KIND_TIMEOUT)
        .tags(customTags)
        .register(meterRegistry);

    timeLimiter.getEventPublisher()
        .onSuccess(event -> successes.increment())
        .onError(event -> failures.increment())
        .onTimeout(event -> timeouts.increment());

    List<Meter.Id> ids = Arrays.asList(successes.getId(), failures.getId(), timeouts.getId());
    meterIdMap.put(timeLimiter.getName(), new HashSet<>(ids));
}
 
示例29
@Test
public void shouldReplaceMetrics() {
    Counter before = meterRegistry.get(DEFAULT_TIME_LIMITER_CALLS).counter();
    assertThat(before).isNotNull();
    assertThat(before.count()).isEqualTo(0);
    assertThat(before.getId().getTag(TagNames.NAME)).isEqualTo(timeLimiter.getName());

    timeLimiterRegistry.replace(timeLimiter.getName(), TimeLimiter.ofDefaults());

    Counter after = meterRegistry.get(DEFAULT_TIME_LIMITER_CALLS).counter();
    assertThat(after).isNotNull();
    assertThat(after.count()).isEqualTo(0);
    assertThat(after.getId().getTag(TagNames.NAME))
        .isEqualTo(TimeLimiter.ofDefaults().getName());
}
 
示例30
@Test
public void shouldUseCustomPrefix() throws Exception {
    TimeLimiter timeLimiter = given("testPre", metricRegistry);
    String expectedPrefix = "testPre.testLimit.";
    Supplier<CompletableFuture<String>> futureSupplier = () ->
        CompletableFuture.completedFuture("Hello world");

    String result = timeLimiter.decorateFutureSupplier(futureSupplier).call();

    then(result).isEqualTo("Hello world");
    assertThat(metricRegistry).hasMetricsSize(3);
    assertThat(metricRegistry).counter(expectedPrefix + SUCCESSFUL)
        .hasValue(1L);
    assertThat(metricRegistry).counter(expectedPrefix + FAILED)
        .hasValue(0L);
    assertThat(metricRegistry).counter(expectedPrefix + TIMEOUT)
        .hasValue(0L);
}