This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new a6f6335fda36 CAMEL-21438: Harden container-exception retry logic and 
isolate IggyConsumerOffsetIT (#24508)
a6f6335fda36 is described below

commit a6f6335fda368947c6002f8250f80c4ca4f9cfe9
Author: Adriano Machado <[email protected]>
AuthorDate: Wed Jul 8 04:03:34 2026 -0400

    CAMEL-21438: Harden container-exception retry logic and isolate 
IggyConsumerOffsetIT (#24508)
    
    Fix isRetryableContainerException short-circuiting on 
NoHttpResponseException by
    walking the cause chain in a separate pass first, so a dead Docker daemon 
fails
    fast instead of being retried. Isolate IggyConsumerOffsetIT on dedicated
    topic/stream/consumer-group names to eliminate shared-state interference.
    
    Co-Authored-By: Claude Sonnet 5 <[email protected]>
---
 .../camel/component/iggy/IggyConsumerOffsetIT.java | 31 ++++++++++++++++++----
 .../apache/camel/component/iggy/IggyTestBase.java  |  8 ++++--
 .../infra/common/services/TestServiceUtil.java     |  5 ++++
 .../common/services/TestServiceUtilRetryTest.java  | 17 ++++++++++++
 4 files changed, 54 insertions(+), 7 deletions(-)

diff --git 
a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerOffsetIT.java
 
b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerOffsetIT.java
index 69838091a72a..e784e3bfc7de 100644
--- 
a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerOffsetIT.java
+++ 
b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerOffsetIT.java
@@ -16,9 +16,12 @@
  */
 package org.apache.camel.component.iggy;
 
+import java.util.stream.IntStream;
+
 import org.apache.camel.RoutesBuilder;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
 
@@ -26,6 +29,10 @@ import 
org.junit.jupiter.api.condition.DisabledIfSystemProperty;
                           disabledReason = "Iggy 0.6.0+ requires io_uring 
which is not available on CI environments")
 public class IggyConsumerOffsetIT extends IggyTestBase {
 
+    private static final String OFFSET_TOPIC = "test-topic-offset";
+    private static final String OFFSET_STREAM = "test-stream-offset";
+    private static final String OFFSET_CONSUMER_GROUP = 
"test-consumer-group-offset";
+
     int startingOffset = 5;
 
     @Test
@@ -35,10 +42,17 @@ public class IggyConsumerOffsetIT extends IggyTestBase {
         mockEndpoint.expectedMessageCount(messages - startingOffset);
 
         for (int i = 0; i < messages; i++) {
-            sendMessage("Message " + i);
+            sendMessage(OFFSET_STREAM, OFFSET_TOPIC, "Message " + i);
         }
 
         mockEndpoint.assertIsSatisfied();
+        Assertions.assertEquals(
+                IntStream.range(startingOffset, messages)
+                        .mapToObj(i -> "Message " + i)
+                        .toList(),
+                mockEndpoint.getExchanges().stream()
+                        .map(exchange -> 
exchange.getMessage().getBody(String.class))
+                        .toList());
 
         // send more messages to check offset update
         int newMessages = 20;
@@ -46,10 +60,17 @@ public class IggyConsumerOffsetIT extends IggyTestBase {
         mockEndpoint.expectedMessageCount(newMessages);
 
         for (int i = 0; i < newMessages; i++) {
-            sendMessage("Second Message " + i);
+            sendMessage(OFFSET_STREAM, OFFSET_TOPIC, "Second Message " + i);
         }
 
         mockEndpoint.assertIsSatisfied();
+        Assertions.assertEquals(
+                IntStream.range(0, newMessages)
+                        .mapToObj(i -> "Second Message " + i)
+                        .toList(),
+                mockEndpoint.getExchanges().stream()
+                        .map(exchange -> 
exchange.getMessage().getBody(String.class))
+                        .toList());
     }
 
     @Override
@@ -58,13 +79,13 @@ public class IggyConsumerOffsetIT extends IggyTestBase {
             @Override
             public void configure() {
                 
fromF("iggy:%s?username=%s&password=%s&streamName=%s&host=%s&port=%d&consumerGroupName=%s&autoCommit=false&startingOffset=%d",
-                        TOPIC,
+                        OFFSET_TOPIC,
                         iggyService.username(),
                         iggyService.password(),
-                        STREAM,
+                        OFFSET_STREAM,
                         iggyService.host(),
                         iggyService.port(),
-                        CONSUMER_GROUP,
+                        OFFSET_CONSUMER_GROUP,
                         startingOffset)
                         .to("mock:result");
             }
diff --git 
a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java
 
b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java
index 81e20f7d0af1..48d859d81059 100644
--- 
a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java
+++ 
b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java
@@ -70,9 +70,13 @@ public abstract class IggyTestBase {
     }
 
     protected void sendMessage(String message) {
+        sendMessage(STREAM, TOPIC, message);
+    }
+
+    protected void sendMessage(String stream, String topic, String message) {
         client.messages().sendMessages(
-                StreamId.of(STREAM),
-                TopicId.of(TOPIC),
+                StreamId.of(stream),
+                TopicId.of(topic),
                 Partitioning.balanced(),
                 Collections.singletonList(Message.of(message)));
     }
diff --git 
a/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/TestServiceUtil.java
 
b/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/TestServiceUtil.java
index 2460c4083a6f..c595c9fea745 100644
--- 
a/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/TestServiceUtil.java
+++ 
b/test-infra/camel-test-infra-common/src/main/java/org/apache/camel/test/infra/common/services/TestServiceUtil.java
@@ -68,6 +68,11 @@ public final class TestServiceUtil {
     }
 
     private static boolean isRetryableContainerException(Throwable e) {
+        for (Throwable t = e; t != null; t = t.getCause()) {
+            if (t.getClass().getName().contains("NoHttpResponseException")) {
+                return false;
+            }
+        }
         for (Throwable t = e; t != null; t = t.getCause()) {
             if (t instanceof ContainerFetchException || t instanceof 
ContainerLaunchException) {
                 return true;
diff --git 
a/test-infra/camel-test-infra-common/src/test/java/org/apache/camel/test/infra/common/services/TestServiceUtilRetryTest.java
 
b/test-infra/camel-test-infra-common/src/test/java/org/apache/camel/test/infra/common/services/TestServiceUtilRetryTest.java
index bffdbad7e6a6..9b114576eb8e 100644
--- 
a/test-infra/camel-test-infra-common/src/test/java/org/apache/camel/test/infra/common/services/TestServiceUtilRetryTest.java
+++ 
b/test-infra/camel-test-infra-common/src/test/java/org/apache/camel/test/infra/common/services/TestServiceUtilRetryTest.java
@@ -96,6 +96,23 @@ class TestServiceUtilRetryTest {
         assertEquals(2, attempts.get());
     }
 
+    @Test
+    void failsImmediatelyOnDockerDaemonNoHttpResponse() throws Exception {
+        AtomicInteger attempts = new AtomicInteger();
+        Throwable noHttpResponse = (Throwable) Class.forName(
+                
"com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.NoHttpResponseException")
+                .getConstructor(String.class)
+                .newInstance("localhost:2375 failed to respond");
+
+        TestService service = new StubTestService(() -> {
+            attempts.incrementAndGet();
+            throw new ContainerLaunchException("Could not start container", 
noHttpResponse);
+        });
+
+        assertThrows(ContainerLaunchException.class, () -> 
TestServiceUtil.tryInitialize(service, null));
+        assertEquals(1, attempts.get());
+    }
+
     @Test
     void succeedsOnFirstAttempt() {
         AtomicInteger attempts = new AtomicInteger();

Reply via email to