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}'")