reactor.util.retry.Retry Java Examples
The following examples show how to use
reactor.util.retry.Retry.
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: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 6 votes |
@Test public void lateOtherEmptyCancelsSourceAndCompletes() { AtomicBoolean sourceSubscribed = new AtomicBoolean(); AtomicBoolean sourceCancelled = new AtomicBoolean(); Flux<Integer> source = justError .doOnSubscribe(sub -> sourceSubscribed.set(true)) .doOnCancel(() -> sourceCancelled.set(true)); Flux<Integer> retry = source.retryWhen(Retry.from(other -> other.take(1))); StepVerifier.create(retry) .expectSubscription() .expectNext(1) //original .expectNext(1) //retry .verifyComplete(); //retry terminated assertThat(sourceSubscribed.get()).isTrue(); assertThat(sourceCancelled.get()).isTrue(); }
Example #2
Source File: DefaultGatewayClient.java From Discord4J with GNU Lesser General Public License v3.0 | 6 votes |
private Retry retryFactory() { return GatewayRetrySpec.create(reconnectOptions, reconnectContext) .doBeforeRetry(retry -> { stateChanges.next(retry.nextState()); long attempt = retry.iteration(); Duration backoff = retry.nextBackoff(); log.debug(format(getContextFromException(retry.failure()), "{} in {} (attempts: {})"), retry.nextState(), backoff, attempt); if (retry.iteration() == 1) { if (retry.nextState() == GatewayConnection.State.RESUMING) { dispatchSink.next(GatewayStateChange.retryStarted(backoff)); notifyObserver(GatewayObserver.RETRY_STARTED); } else { dispatchSink.next(GatewayStateChange.retryStartedResume(backoff)); notifyObserver(GatewayObserver.RETRY_RESUME_STARTED); } } else { dispatchSink.next(GatewayStateChange.retryFailed(attempt - 1, backoff)); notifyObserver(GatewayObserver.RETRY_FAILED); } }); }
Example #3
Source File: ReconnectMonoTests.java From rsocket-java with Apache License 2.0 | 6 votes |
@Test public void shouldTimeoutRetryWithVirtualTime() { // given final int minBackoff = 1; final int maxBackoff = 5; final int timeout = 10; // then StepVerifier.withVirtualTime( () -> Mono.<String>error(new RuntimeException("Something went wrong")) .retryWhen( Retry.backoff(Long.MAX_VALUE, Duration.ofSeconds(minBackoff)) .doAfterRetry(onRetry()) .maxBackoff(Duration.ofSeconds(maxBackoff))) .timeout(Duration.ofSeconds(timeout)) .as(m -> new ReconnectMono<>(m, onExpire(), onValue())) .subscribeOn(Schedulers.elastic())) .expectSubscription() .thenAwait(Duration.ofSeconds(timeout)) .expectError(TimeoutException.class) .verify(Duration.ofSeconds(timeout)); Assertions.assertThat(received).isEmpty(); Assertions.assertThat(expired).isEmpty(); }
Example #4
Source File: ReconnectMonoTests.java From rsocket-java with Apache License 2.0 | 6 votes |
@Test public void monoRetryFixedBackoff() { Mono<?> mono = Mono.error(new IOException()) .retryWhen(Retry.fixedDelay(1, Duration.ofMillis(500)).doAfterRetry(onRetry())) .as(m -> new ReconnectMono<>(m, onExpire(), onValue())); StepVerifier.withVirtualTime(() -> mono) .expectSubscription() .expectNoEvent(Duration.ofMillis(300)) .thenAwait(Duration.ofMillis(300)) .verifyErrorMatches(Exceptions::isRetryExhausted); assertRetries(IOException.class); Assertions.assertThat(received).isEmpty(); Assertions.assertThat(expired).isEmpty(); }
Example #5
Source File: SharedPollingTopicListener.java From hedera-mirror-node with Apache License 2.0 | 6 votes |
public SharedPollingTopicListener(ListenerProperties listenerProperties, TopicMessageRepository topicMessageRepository, InstantToLongConverter instantToLongConverter) { this.listenerProperties = listenerProperties; this.topicMessageRepository = topicMessageRepository; this.instantToLongConverter = instantToLongConverter; Scheduler scheduler = Schedulers.newSingle("shared-poll", true); Duration frequency = listenerProperties.getPollingFrequency(); PollingContext context = new PollingContext(); poller = Flux.defer(() -> poll(context) .subscribeOn(scheduler) .publishOn(Schedulers.boundedElastic())) .repeatWhen(Repeat.times(Long.MAX_VALUE) .fixedBackoff(frequency) .withBackoffScheduler(scheduler)) .name("shared-poll") .metrics() .doOnCancel(() -> log.info("Cancelled polling")) .doOnError(t -> log.error("Error polling the database", t)) .doOnNext(context::onNext) .doOnSubscribe(context::onStart) .retryWhen(Retry.backoff(Long.MAX_VALUE, frequency).maxBackoff(frequency.multipliedBy(4L))) .share(); }
Example #6
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 6 votes |
@Test public void backoffFunctionTransient() { Flux<Integer> source = transientErrorSource(); Retry retryFunction = Retry.backoff(2, Duration.ZERO) .maxBackoff(Duration.ofMillis(100)) .jitter(0d) .transientErrors(true); new FluxRetryWhen<>(source, retryFunction) .as(StepVerifier::create) .expectNext(3, 4, 7, 8, 11, 12) .expectComplete() .verify(Duration.ofSeconds(2)); }
Example #7
Source File: GuideTests.java From reactor-core with Apache License 2.0 | 6 votes |
@Test public void errorHandlingRetryWhenEquatesRetry() { AtomicInteger errorCount = new AtomicInteger(); Flux<String> flux = Flux.<String>error(new IllegalArgumentException()) .doOnError(e -> errorCount.incrementAndGet()) .retryWhen(Retry.from(companion -> // <1> companion.map(rs -> { // <2> if (rs.totalRetries() < 3) return rs.totalRetries(); // <3> else throw Exceptions.propagate(rs.failure()); // <4> }) )); StepVerifier.create(flux) .verifyError(IllegalArgumentException.class); AtomicInteger retryNErrorCount = new AtomicInteger(); StepVerifier.create(Flux.<String>error(new IllegalArgumentException()).doOnError(e -> retryNErrorCount.incrementAndGet()).retry(3)) .verifyError(); assertThat(errorCount).hasValue(retryNErrorCount.get()); }
Example #8
Source File: KeyRegistrationHandler.java From james-project with Apache License 2.0 | 6 votes |
@VisibleForTesting void declareQueue() { sender.declareQueue(QueueSpecification.queue(EVENTBUS_QUEUE_NAME_PREFIX + eventBusId.asString()) .durable(DURABLE) .exclusive(!EXCLUSIVE) .autoDelete(AUTO_DELETE) .arguments(QUEUE_ARGUMENTS)) .map(AMQP.Queue.DeclareOk::getQueue) .retryWhen(Retry.backoff(retryBackoff.getMaxRetries(), retryBackoff.getFirstBackoff()).jitter(retryBackoff.getJitterFactor())) .doOnSuccess(queueName -> { if (!registrationQueueInitialized.get()) { registrationQueue.initialize(queueName); registrationQueueInitialized.set(true); } }) .block(); }
Example #9
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 6 votes |
@Test public void backoffFunctionNotTransient() { Flux<Integer> source = transientErrorSource(); Retry retryFunction = Retry.backoff(2, Duration.ZERO) .maxBackoff(Duration.ofMillis(100)) .jitter(0d) .transientErrors(false); new FluxRetryWhen<>(source, retryFunction) .as(StepVerifier::create) .expectNext(3, 4) .expectErrorMessage("Retries exhausted: 2/2") .verify(Duration.ofSeconds(2)); }
Example #10
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 6 votes |
@Test public void fluxRetryRandomBackoff_noRandomness() { Exception exception = new IOException("boom retry"); List<Long> elapsedList = new ArrayList<>(); StepVerifier.withVirtualTime(() -> Flux.concat(Flux.range(0, 2), Flux.error(exception)) .retryWhen(Retry .backoff(4, Duration.ofMillis(100)) .maxBackoff(Duration.ofMillis(2000)) .jitter(0) ) .elapsed() .doOnNext(elapsed -> { if (elapsed.getT2() == 0) elapsedList.add(elapsed.getT1());} ) .map(Tuple2::getT2) ) .thenAwait(Duration.ofMinutes(1)) //ensure whatever the jittered delay that we have time to fit 4 retries .expectNext(0, 1) //normal output .expectNext(0, 1, 0, 1, 0, 1, 0, 1) //4 retry attempts .expectErrorSatisfies(e -> assertThat(e).isInstanceOf(IllegalStateException.class) .hasMessage("Retries exhausted: 4/4") .hasCause(exception)) .verify(Duration.ofSeconds(1)); //vts test shouldn't even take that long assertThat(elapsedList).containsExactly(0L, 100L, 200L, 400L, 800L); }
Example #11
Source File: ReconnectMonoTests.java From rsocket-java with Apache License 2.0 | 6 votes |
@Test public void monoRetryExponentialBackoff() { Mono<?> mono = Mono.error(new IOException()) .retryWhen( Retry.backoff(4, Duration.ofMillis(100)) .maxBackoff(Duration.ofMillis(500)) .jitter(0.0d) .doAfterRetry(onRetry())) .as(m -> new ReconnectMono<>(m, onExpire(), onValue())); StepVerifier.withVirtualTime(() -> mono) .expectSubscription() .thenAwait(Duration.ofMillis(100)) .thenAwait(Duration.ofMillis(200)) .thenAwait(Duration.ofMillis(400)) .thenAwait(Duration.ofMillis(500)) .verifyErrorMatches(Exceptions::isRetryExhausted); assertRetries(IOException.class, IOException.class, IOException.class, IOException.class); Assertions.assertThat(received).isEmpty(); Assertions.assertThat(expired).isEmpty(); }
Example #12
Source File: MonoRetryWhenTest.java From reactor-core with Apache License 2.0 | 6 votes |
@Test public void monoRetryBackoffWithGivenScheduler() { VirtualTimeScheduler backoffScheduler = VirtualTimeScheduler.create(); Exception exception = new IOException("boom retry"); AtomicInteger errorCount = new AtomicInteger(); StepVerifier.create( Mono.error(exception) .doOnError(t -> errorCount.incrementAndGet()) .retryWhen(Retry.backoff(4, Duration.ofMillis(10)) .maxBackoff(Duration.ofMillis(100)) .jitter(0) .scheduler(backoffScheduler) ) ) .expectSubscription() .expectNoEvent(Duration.ofMillis(400)) .then(() -> assertThat(errorCount).as("errorCount before advanceTime").hasValue(1)) .then(() -> backoffScheduler.advanceTimeBy(Duration.ofMillis(400))) .then(() -> assertThat(errorCount).as("errorCount after advanceTime").hasValue(5)) .expectErrorSatisfies(e -> assertThat(e).isInstanceOf(IllegalStateException.class) .hasMessage("Retries exhausted: 4/4") .hasCause(exception)) .verify(Duration.ofMillis(400)); //test should only take roughly the expectNoEvent time }
Example #13
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 6 votes |
@Test public void directOtherErrorPreventsSubscribe() { AtomicBoolean sourceSubscribed = new AtomicBoolean(); AtomicBoolean sourceCancelled = new AtomicBoolean(); Flux<Integer> source = justError .doOnSubscribe(sub -> sourceSubscribed.set(true)) .doOnCancel(() -> sourceCancelled.set(true)); Flux<Integer> retry = source.retryWhen(Retry.from(other -> Mono.error(new IllegalStateException("boom")))); StepVerifier.create(retry) .expectSubscription() .verifyErrorMessage("boom"); assertThat(sourceSubscribed.get()).isFalse(); assertThat(sourceCancelled.get()).isFalse(); }
Example #14
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 6 votes |
@Test public void lateOtherErrorCancelsSource() { AtomicBoolean sourceSubscribed = new AtomicBoolean(); AtomicBoolean sourceCancelled = new AtomicBoolean(); AtomicInteger count = new AtomicInteger(); Flux<Integer> source = justError .doOnSubscribe(sub -> sourceSubscribed.set(true)) .doOnCancel(() -> sourceCancelled.set(true)); Flux<Integer> retry = source.retryWhen(Retry.from(other -> other.flatMap(l -> count.getAndIncrement() == 0 ? Mono.just(l) : Mono.<Long>error(new IllegalStateException("boom"))))); StepVerifier.create(retry) .expectSubscription() .expectNext(1) .expectNext(1) .verifyErrorMessage("boom"); assertThat(sourceSubscribed.get()).isTrue(); assertThat(sourceCancelled.get()).isTrue(); }
Example #15
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 5 votes |
@Test public void gh1978() { final int elementPerCycle = 3; final int stopAfterCycles = 10; Flux<Long> source = Flux.generate(() -> new AtomicLong(0), (counter, s) -> { long currentCount = counter.incrementAndGet(); if (currentCount % elementPerCycle == 0) { s.error(new RuntimeException("Error!")); } else { s.next(currentCount); } return counter; }); List<Long> pauses = new ArrayList<>(); StepVerifier.withVirtualTime(() -> source.retryWhen(Retry .backoff(Long.MAX_VALUE, Duration.ofSeconds(1)) .maxBackoff(Duration.ofMinutes(1)) .jitter(0d) .transientErrors(true) ) .take(stopAfterCycles * elementPerCycle) .elapsed() .map(Tuple2::getT1) .doOnNext(pause -> { if (pause > 500) pauses.add(pause / 1000); }) ) .thenAwait(Duration.ofHours(1)) .expectNextCount(stopAfterCycles * elementPerCycle) .expectComplete() .verify(Duration.ofSeconds(1)); assertThat(pauses).allMatch(p -> p == 1, "pause is constantly 1s"); }
Example #16
Source File: CassandraUidProvider.java From james-project with Apache License 2.0 | 5 votes |
public Mono<MessageUid> nextUid(CassandraId cassandraId) { Mono<MessageUid> updateUid = findHighestUid(cassandraId) .flatMap(messageUid -> tryUpdateUid(cassandraId, messageUid)); Duration firstBackoff = Duration.ofMillis(10); return updateUid .switchIfEmpty(tryInsert(cassandraId)) .switchIfEmpty(updateUid) .single() .retryWhen(Retry.backoff(maxUidRetries, firstBackoff).scheduler(Schedulers.elastic())); }
Example #17
Source File: ReactorRabbitMQChannelPool.java From james-project with Apache License 2.0 | 5 votes |
private Mono<Channel> openChannel(Connection connection) { return Mono.fromCallable(connection::openChannel) .map(maybeChannel -> maybeChannel.orElseThrow(() -> new RuntimeException("RabbitMQ reached to maximum opened channels, cannot get more channels"))) .retryWhen(Retry.backoff(MAX_RETRIES, RETRY_FIRST_BACK_OFF).scheduler(Schedulers.elastic())) .doOnError(throwable -> LOGGER.error("error when creating new channel", throwable)); }
Example #18
Source File: MailDispatcher.java From james-project with Apache License 2.0 | 5 votes |
private Mono<Void> storeMailWithRetry(Mail mail, MailAddress recipient) { return Mono.fromRunnable((ThrowingRunnable)() -> mailStore.storeMail(recipient, mail)) .doOnError(error -> LOGGER.error("Error While storing mail.", error)) .subscribeOn(scheduler) .retryWhen(Retry.backoff(RETRIES, FIRST_BACKOFF).maxBackoff(MAX_BACKOFF).scheduler(Schedulers.elastic())) .then(); }
Example #19
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 5 votes |
Flux<String> fixedDelaysRetryScenario() { AtomicInteger i = new AtomicInteger(); return Flux.<String>create(s -> { if (i.incrementAndGet() == 4) { s.next("hey"); s.complete(); } else { s.error(new RuntimeException("test " + i)); } }).retryWhen(Retry.fixedDelay(3, Duration.ofSeconds(3)) .doBeforeRetry(rs -> System.out.println(rs.copy())) ); }
Example #20
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 5 votes |
@SuppressWarnings("deprecation") @Test public void retryWhenThrowableCompanionIsComparableToRetryWhenRetryFromFunction() { AtomicInteger sourceHelper = new AtomicInteger(); Flux<Integer> source = Flux.create(sink -> { if (sourceHelper.getAndIncrement() == 3) { sink.next(1).next(2).next(3).complete(); } else { sink.error(new IllegalStateException("boom")); } }); StepVerifier.withVirtualTime(() -> source.retryWhen(companion -> companion.delayElements(Duration.ofSeconds(3)))) .expectSubscription() .expectNoEvent(Duration.ofSeconds(3 * 3)) .expectNext(1, 2, 3) .verifyComplete(); sourceHelper.set(0); StepVerifier.withVirtualTime(() -> source.retryWhen( Retry.from(companion -> companion.delayElements(Duration.ofSeconds(3)))) ) .expectSubscription() .expectNoEvent(Duration.ofSeconds(3 * 3)) .expectNext(1, 2, 3) .verifyComplete(); }
Example #21
Source File: KeyRegistrationHandler.java From james-project with Apache License 2.0 | 5 votes |
Mono<Registration> register(MailboxListener.ReactiveMailboxListener listener, RegistrationKey key) { LocalListenerRegistry.LocalRegistration registration = localListenerRegistry.addListener(key, listener); return registerIfNeeded(key, registration) .thenReturn(new KeyRegistration(() -> { if (registration.unregister().lastListenerRemoved()) { registrationBinder.unbind(key) .retryWhen(Retry.backoff(retryBackoff.getMaxRetries(), retryBackoff.getFirstBackoff()).jitter(retryBackoff.getJitterFactor()).scheduler(Schedulers.elastic())) .subscribeOn(Schedulers.elastic()) .block(); } })); }
Example #22
Source File: ResilientClusterProvider.java From james-project with Apache License 2.0 | 5 votes |
@VisibleForTesting @Inject ResilientClusterProvider(ClusterConfiguration configuration) { Duration waitDelay = Duration.ofMillis(configuration.getMinDelay()); cluster = Mono.fromCallable(getClusterRetryCallable(configuration)) .doOnError(e -> LOGGER.warn("Error establishing Cassandra connection. Next retry scheduled in {} ms", waitDelay, e)) .retryWhen(Retry.backoff(configuration.getMaxRetry(), waitDelay).scheduler(Schedulers.elastic())) .publishOn(Schedulers.elastic()) .block(); }
Example #23
Source File: ClientProvider.java From james-project with Apache License 2.0 | 5 votes |
private RestHighLevelClient connect(ElasticSearchConfiguration configuration) { Duration waitDelay = Duration.ofMillis(configuration.getMinDelay()); boolean suppressLeadingZeroElements = true; boolean suppressTrailingZeroElements = true; return Mono.fromCallable(() -> connectToCluster(configuration)) .doOnError(e -> LOGGER.warn("Error establishing ElasticSearch connection. Next retry scheduled in {}", DurationFormatUtils.formatDurationWords(waitDelay.toMillis(), suppressLeadingZeroElements, suppressTrailingZeroElements), e)) .retryWhen(Retry.backoff(configuration.getMaxRetries(), waitDelay).scheduler(Schedulers.elastic())) .publishOn(Schedulers.elastic()) .block(); }
Example #24
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 5 votes |
@Test public void whenFactoryReturnsNull() { AssertSubscriber<Integer> ts = AssertSubscriber.create(); rangeError.retryWhen(Retry.from(other -> null)) .subscribe(ts); ts.assertNoValues() .assertError(NullPointerException.class) .assertNotComplete(); }
Example #25
Source File: ReconnectMonoTests.java From rsocket-java with Apache License 2.0 | 5 votes |
@Test public void monoRetryNoBackoff() { Mono<?> mono = Mono.error(new IOException()) .retryWhen(Retry.max(2).doAfterRetry(onRetry())) .as(m -> new ReconnectMono<>(m, onExpire(), onValue())); StepVerifier.create(mono).verifyErrorMatches(Exceptions::isRetryExhausted); assertRetries(IOException.class, IOException.class); Assertions.assertThat(received).isEmpty(); Assertions.assertThat(expired).isEmpty(); }
Example #26
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 5 votes |
@Test public void whenFactoryThrows() { AssertSubscriber<Integer> ts = AssertSubscriber.create(); rangeError.retryWhen(Retry.from(other -> { throw new RuntimeException("forced failure"); })) .subscribe(ts); ts.assertNoValues() .assertError(RuntimeException.class) .assertErrorMessage("forced failure") .assertNotComplete(); }
Example #27
Source File: StreamCompatibleBlobPutter.java From james-project with Apache License 2.0 | 5 votes |
@Override public Mono<Void> putDirectly(ObjectStorageBucketName bucketName, Blob blob) { return Mono.fromRunnable(() -> blobStore.putBlob(bucketName.asString(), blob)) .publishOn(Schedulers.elastic()) .retryWhen(Retry .backoff(MAX_RETRIES, FIRST_BACK_OFF) .filter(throwable -> needToCreateBucket(throwable, bucketName)) .doBeforeRetry(retryContext -> blobStore.createContainerInLocation(DEFAULT_LOCATION, bucketName.asString()))) .retryWhen(Retry .backoff(RETRY_ONE_LAST_TIME_ON_CONCURRENT_SAVING, FIRST_BACK_OFF) .filter(this::isPutMethod) .scheduler(Schedulers.elastic())) .then(); }
Example #28
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 5 votes |
@Test public void coldError() { AssertSubscriber<Integer> ts = AssertSubscriber.create(0); rangeError.retryWhen(Retry.from(other -> Flux.error(new RuntimeException("forced failure")))) .subscribe(ts); ts.assertNoValues() .assertError(RuntimeException.class) .assertErrorMessage("forced failure") .assertNotComplete(); }
Example #29
Source File: CassandraMessageMapper.java From james-project with Apache License 2.0 | 5 votes |
private Mono<Void> insertIds(MailboxMessage message, CassandraId mailboxId) { ComposedMessageIdWithMetaData composedMessageIdWithMetaData = ComposedMessageIdWithMetaData.builder() .composedMessageId(new ComposedMessageId(mailboxId, message.getMessageId(), message.getUid())) .flags(message.createFlags()) .modSeq(message.getModSeq()) .build(); return imapUidDAO.insert(composedMessageIdWithMetaData) .then(Flux.merge( messageIdDAO.insert(composedMessageIdWithMetaData) .retryWhen(Retry.backoff(MAX_RETRY, MIN_RETRY_BACKOFF).maxBackoff(MAX_RETRY_BACKOFF)), indexTableHandler.updateIndexOnAdd(message, mailboxId)) .then()); }
Example #30
Source File: FluxRetryWhenTest.java From reactor-core with Apache License 2.0 | 5 votes |
@Test public void fluxRetryRandomBackoffDefaultJitter() { Exception exception = new IOException("boom retry"); List<Long> elapsedList = new ArrayList<>(); StepVerifier.withVirtualTime(() -> Flux.concat(Flux.range(0, 2), Flux.error(exception)) .retryWhen(Retry .backoff(4, Duration.ofMillis(100)) .maxBackoff(Duration.ofMillis(2000)) ) .elapsed() .doOnNext(elapsed -> { if (elapsed.getT2() == 0) elapsedList.add(elapsed.getT1());} ) .map(Tuple2::getT2) ) .thenAwait(Duration.ofMinutes(1)) //ensure whatever the jittered delay that we have time to fit 4 retries .expectNext(0, 1) //normal output .expectNext(0, 1, 0, 1, 0, 1, 0, 1) //4 retry attempts .expectErrorSatisfies(e -> assertThat(e).isInstanceOf(IllegalStateException.class) .hasMessage("Retries exhausted: 4/4") .hasCause(exception)) .verify(Duration.ofSeconds(1)); //vts test shouldn't even take that long assertThat(elapsedList).hasSize(5); assertThat(elapsedList, LongAssert.class).first() .isEqualTo(0L); assertThat(elapsedList, LongAssert.class).element(1) .isCloseTo(100, Percentage.withPercentage(50)); assertThat(elapsedList, LongAssert.class).element(2) .isCloseTo(200, Percentage.withPercentage(50)); assertThat(elapsedList, LongAssert.class).element(3) .isCloseTo(400, Percentage.withPercentage(50)); assertThat(elapsedList, LongAssert.class).element(4) .isCloseTo(800, Percentage.withPercentage(50)); }