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

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

commit 55f17fb9e468f5b3201518bcdb3de8cb7255c037
Author: smjain <[email protected]>
AuthorDate: Wed Sep 23 17:09:12 2026 +0530

    CAMEL-24922: camel-core - Test sticky failover wrap around with 
maximumFailoverAttempts
    
    Assert the failed attempts on a and b when setting up the last known good
    endpoint, and test that maximumFailoverAttempts still bounds the failover 
when
    sticky mode wraps around to the first endpoint.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../processor/FailoverStickyWrapAroundTest.java    | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git 
a/core/camel-core/src/test/java/org/apache/camel/processor/FailoverStickyWrapAroundTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/processor/FailoverStickyWrapAroundTest.java
index 6bd3909596dc..aee129605896 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/processor/FailoverStickyWrapAroundTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/processor/FailoverStickyWrapAroundTest.java
@@ -67,6 +67,8 @@ public class FailoverStickyWrapAroundTest extends 
ContextTestSupport {
     public void testFailoverStickyTriesEachEndpointOnceWhenAllDown() throws 
Exception {
         down.add("a");
         down.add("b");
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:b").expectedMessageCount(1);
         getMockEndpoint("mock:c").expectedMessageCount(1);
         template.sendBody("direct:start", "Hello World");
         assertMockEndpointsSatisfied();
@@ -80,6 +82,41 @@ public class FailoverStickyWrapAroundTest extends 
ContextTestSupport {
         assertMockEndpointsSatisfied();
     }
 
+    @Test
+    public void testFailoverStickyWrapAroundRespectsMaximumFailoverAttempts() 
throws Exception {
+        // a and b are down, so c becomes the last known good endpoint (2 
failover attempts)
+        down.add("a");
+        down.add("b");
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:b").expectedMessageCount(1);
+        getMockEndpoint("mock:c").expectedMessageCount(1);
+        getMockEndpoint("mock:d").expectedMessageCount(0);
+        template.sendBody("direct:limited", "Hello World");
+        assertMockEndpointsSatisfied();
+
+        // all down: sticky starts from c, fails over to d, then wraps around 
to a, which uses up the
+        // 2 failover attempts, so b is not tried
+        resetMocks();
+        down.add("c");
+        down.add("d");
+        getMockEndpoint("mock:a").expectedMessageCount(1);
+        getMockEndpoint("mock:b").expectedMessageCount(0);
+        getMockEndpoint("mock:c").expectedMessageCount(1);
+        getMockEndpoint("mock:d").expectedMessageCount(1);
+        assertThrows(CamelExecutionException.class, () -> 
template.sendBody("direct:limited", "Bye World"));
+        assertMockEndpointsSatisfied();
+
+        // a is up again: reached with the last failover attempt after the 
wrap around
+        resetMocks();
+        down.remove("a");
+        getMockEndpoint("mock:a").expectedBodiesReceived("Hi World");
+        getMockEndpoint("mock:b").expectedMessageCount(0);
+        getMockEndpoint("mock:c").expectedMessageCount(1);
+        getMockEndpoint("mock:d").expectedMessageCount(1);
+        template.sendBody("direct:limited", "Hi World");
+        assertMockEndpointsSatisfied();
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() {
         return new RouteBuilder() {
@@ -89,9 +126,14 @@ public class FailoverStickyWrapAroundTest extends 
ContextTestSupport {
                         .loadBalance().failover(-1, false, false, true)
                         .to("direct:a", "direct:b", "direct:c");
 
+                from("direct:limited")
+                        .loadBalance().failover(2, false, false, true)
+                        .to("direct:a", "direct:b", "direct:c", "direct:d");
+
                 from("direct:a").to("mock:a").process(e -> failIfDown("a"));
                 from("direct:b").to("mock:b").process(e -> failIfDown("b"));
                 from("direct:c").to("mock:c").process(e -> failIfDown("c"));
+                from("direct:d").to("mock:d").process(e -> failIfDown("d"));
             }
         };
     }

Reply via email to