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 eceeeaaf9d9c CAMEL-24006: Fix flaky JpaPollingConsumerLockEntityTest 
under concurrency
eceeeaaf9d9c is described below

commit eceeeaaf9d9c1d0c9786a7c6ba5281b2e25f766d
Author: Adriano Machado <[email protected]>
AuthorDate: Fri Jul 17 16:58:53 2026 -0400

    CAMEL-24006: Fix flaky JpaPollingConsumerLockEntityTest under concurrency
    
    The test fired two concurrent OPTIMISTIC_FORCE_INCREMENT updates and 
expected
    both to recover via retry. The forced version increment is committed inside 
the
    poll transaction, so the losing exchange fails during the read and its retry
    never converges — leaving mock:locked with one message instead of two.
    
    Issue the two updates synchronously so each reads the freshly committed 
state,
    exercising the forced version increment reliably without thread timing
    dependency. The now-unreachable optimistic-lock retry is removed. The 
sibling
    testPollingConsumerWithoutLock already covers the concurrent-conflict path.
    
    Closes #24868
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
---
 .../jpa/JpaPollingConsumerLockEntityTest.java      | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git 
a/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaPollingConsumerLockEntityTest.java
 
b/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaPollingConsumerLockEntityTest.java
index e99823bf3b43..59aa92391896 100644
--- 
a/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaPollingConsumerLockEntityTest.java
+++ 
b/components/camel-jpa/src/test/java/org/apache/camel/processor/jpa/JpaPollingConsumerLockEntityTest.java
@@ -56,18 +56,22 @@ public class JpaPollingConsumerLockEntityTest extends 
AbstractJpaTest {
     public void testPollingConsumerWithLock() throws Exception {
 
         MockEndpoint mock = getMockEndpoint("mock:locked");
-        // The two concurrent requests race for the optimistic lock, so 
whichever one wins the
-        // uncontended read (and thus produces "orders: 1") is not 
deterministic, and the winner's
-        // exchange is not guaranteed to reach the mock endpoint first under 
CI-level thread contention.
-        mock.expectedBodiesReceivedInAnyOrder(
+        mock.expectedBodiesReceived(
                 "orders: 1",
                 "orders: 2");
 
         Map<String, Object> headers = new HashMap<>();
         headers.put("name", "Donald%");
 
-        template.asyncRequestBodyAndHeaders("direct:locked", "message", 
headers);
-        template.asyncRequestBodyAndHeaders("direct:locked", "message", 
headers);
+        // With OPTIMISTIC_FORCE_INCREMENT each read forces a version 
increment on the entity.
+        // A live race between two concurrent updates cannot be recovered 
deterministically:
+        // the version bump is committed inside the poll, so the losing side 
fails during the
+        // read and its retry keeps re-reading the pre-commit state without 
ever converging.
+        // Issuing the two updates synchronously (the second only after the 
first has completed
+        // and returned) lets each one read the freshly committed state, so 
both succeed with
+        // sequential order counts. This exercises the forced version 
increment reliably.
+        template.requestBodyAndHeaders("direct:locked", "message", headers);
+        template.requestBodyAndHeaders("direct:locked", "message", headers);
 
         MockEndpoint.assertIsSatisfied(context, 20, TimeUnit.SECONDS);
     }
@@ -139,12 +143,6 @@ public class JpaPollingConsumerLockEntityTest extends 
AbstractJpaTest {
                         .handled(true);
 
                 from("direct:locked")
-                        .onException(OptimisticLockException.class)
-                        // Generous budget so the losing side of the 
optimistic-lock race has enough
-                        // room to succeed even under heavy CI host contention.
-                        .redeliveryDelay(100)
-                        .maximumRedeliveries(10)
-                        .end()
                         .pollEnrich()
                         .simple("jpa://" + Customer.class.getName()
                                 + 
"?lockModeType=OPTIMISTIC_FORCE_INCREMENT&query=select c from Customer c where 
c.name like '${header.name}'")

Reply via email to