diff --git a/implementation/src/main/java/io/smallrye/mutiny/helpers/ExponentialBackoff.java b/implementation/src/main/java/io/smallrye/mutiny/helpers/ExponentialBackoff.java index 3740133f3..e000d80e9 100644 --- a/implementation/src/main/java/io/smallrye/mutiny/helpers/ExponentialBackoff.java +++ b/implementation/src/main/java/io/smallrye/mutiny/helpers/ExponentialBackoff.java @@ -117,11 +117,11 @@ public Publisher apply(Multi t) { long checkTime = System.currentTimeMillis() + delay.toMillis(); if (checkTime > expireAt) { - return Uni.createFrom().failure( + failure.addSuppressed( new IllegalStateException( "Retries exhausted : " + iteration + " attempts against " + checkTime + "/" + expireAt - + " expiration", - failure)); + + " expiration")); + return Uni.createFrom().failure(failure); } return Uni.createFrom().item((long) iteration).onItem().delayIt() .onExecutor(executor).by(delay); diff --git a/implementation/src/test/java/io/smallrye/mutiny/groups/UniOnFailureRetryTest.java b/implementation/src/test/java/io/smallrye/mutiny/groups/UniOnFailureRetryTest.java index 8cb29bf3c..1a9d34596 100644 --- a/implementation/src/test/java/io/smallrye/mutiny/groups/UniOnFailureRetryTest.java +++ b/implementation/src/test/java/io/smallrye/mutiny/groups/UniOnFailureRetryTest.java @@ -216,24 +216,62 @@ public void testRetryWithBackOffReachingMaxAttempt() { @Test public void testRetryWithBackOffReachingExpiresIn() { - assertThrows(IllegalStateException.class, () -> { + assertThatThrownBy(() -> { AtomicInteger count = new AtomicInteger(); Uni.createFrom(). emitter(e -> e.fail(new Exception("boom " + count.getAndIncrement()))) .onFailure().retry().withBackOff(Duration.ofMillis(10), Duration.ofSeconds(20)).withJitter(1.0) .expireIn(90L) .await().atMost(Duration.ofSeconds(5)); - }); + }).cause() + .hasMessageContaining("boom") + .satisfies(t -> assertThat(t.getSuppressed()) + .hasSize(1) + .allSatisfy(s -> assertThat(s) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Retries exhausted"))); } @Test public void testRetryWithBackOffReachingExpiresAt() { - assertThrows(IllegalStateException.class, () -> { + assertThatThrownBy(() -> { AtomicInteger count = new AtomicInteger(); Uni.createFrom(). emitter(e -> e.fail(new Exception("boom " + count.getAndIncrement()))) .onFailure().retry().withBackOff(Duration.ofMillis(10), Duration.ofSeconds(20)).withJitter(1.0) .expireAt(System.currentTimeMillis() + 90L) .await().atMost(Duration.ofSeconds(5)); - }); + }).cause() + .hasMessageContaining("boom") + .satisfies(t -> assertThat(t.getSuppressed()) + .hasSize(1) + .allSatisfy(s -> assertThat(s) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Retries exhausted"))); + } + + @Test + public void testRetryWithBackOffReachingExpiresInPropagatesLastFailure() { + assertThatThrownBy(() -> { + AtomicInteger count = new AtomicInteger(); + Uni.createFrom(). emitter(e -> e.fail(new Exception("boom " + count.getAndIncrement()))) + .onFailure().retry().withBackOff(Duration.ofMillis(10), Duration.ofSeconds(20)).withJitter(1.0) + .expireIn(90L) + .await().atMost(Duration.ofSeconds(5)); + }).isNotInstanceOf(IllegalStateException.class) + .cause() + .hasMessageContaining("boom"); + } + + @Test + public void testRetryWithBackOffReachingExpiresAtPropagatesLastFailure() { + assertThatThrownBy(() -> { + AtomicInteger count = new AtomicInteger(); + Uni.createFrom(). emitter(e -> e.fail(new Exception("boom " + count.getAndIncrement()))) + .onFailure().retry().withBackOff(Duration.ofMillis(10), Duration.ofSeconds(20)).withJitter(1.0) + .expireAt(System.currentTimeMillis() + 90L) + .await().atMost(Duration.ofSeconds(5)); + }).isNotInstanceOf(IllegalStateException.class) + .cause() + .hasMessageContaining("boom"); } @Test