[
https://issues.apache.org/jira/browse/CAMEL-25816?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Claus Ibsen updated CAMEL-25816:
--------------------------------
Fix Version/s: 4.24.0
> camel-hazelcast - a transacted hazelcast-seda consumer whose route continues
> on another thread never commits: processed messages come back when the
> application leaves the cluster, failed ones are not retried
> ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25816
> URL: https://issues.apache.org/jira/browse/CAMEL-25816
> Project: Camel
> Issue Type: Bug
> Components: camel-hazelcast
> Reporter: shashank
> Assignee: shashank
> Priority: Major
> Fix For: 4.24.0
>
>
> {{HazelcastSedaConsumer}} (main 936d6f4517a0, {{run()}} lines 86-180,
> callback at 116-135) begins a Hazelcast transaction on its polling thread
> when {{transacted=true}}, polls the message inside it, and hands the exchange
> to the asynchronous routing engine ({{processor.process(exchange,
> callback)}}). The {{done}} callback commits the transaction, or rolls it back
> when the exchange failed or was marked rollback only.
> A Hazelcast transaction belongs to the thread that began it:
> {{TransactionImpl.commit()}} and {{rollback()}} check the thread and throw
> {{IllegalStateException: Transaction cannot span multiple threads!}} on any
> other thread (Hazelcast 5.4.0). When the route continues on another thread,
> the callback runs there. That is the case with an asynchronous producer, for
> example camel-kafka (the Kafka producer continues routing on its worker
> pool), netty or vertx-http, and with {{threads()}} or an asynchronous delay.
> Then:
> * the commit fails; the reactive executor logs {{WARN Error executing
> reactive work due to Transaction cannot span multiple threads!. This
> exception is ignored.}} and the message stays reserved by a transaction that
> never ends;
> * a failed exchange is not rolled back either, so the failed message is not
> taken again (the documented transacted behaviour), it just disappears from
> the queue;
> * the next poll on the consumer thread fails with {{Nested transactions are
> not allowed!}} (the open transaction is still bound to the thread), is
> reported to the exception handler and waits {{onErrorDelay}};
> * when the application leaves the Hazelcast cluster (a restart or a
> redeploy), the other members roll back the transactions it left open, so
> every message the route processed since it started is put back into the queue
> and consumed again.
> The option says the messages "will only be removed if the transaction
> commits, which happens when the processing is complete"; here they are never
> removed, and are consumed twice.
> *Fix*: with {{transacted=true}} the consumer thread processes the exchange
> synchronously (it waits for the exchange to complete, also when the route
> continued on another thread) and commits or rolls back the transaction
> itself; the non-transacted path is unchanged. A transacted consumer thread
> then takes the next message only when the previous one is complete
> ({{concurrentConsumers}} gives more threads). Option description and upgrade
> note (4.24) updated.
> *Tests*: new {{HazelcastSedaTransactedAsyncRouteTest}} (2 tests, two embedded
> Hazelcast members on the loopback interface, a route with {{threads(1)}}).
> {{testCompletedExchangesAreCommitted}} routes three messages, stops the route
> and shuts down the application's member; on main the remaining member gets
> them back: {{The processed messages were not removed from the queue ==>
> expected: <0> but was: <3>}}. {{testFailedExchangeIsRolledBack}} fails the
> first attempt; on main the message is never taken again: {{mock://failed
> Received message count. Expected: <1> but was: <0>}}. Both pass with the fix
> (3 runs). camel-hazelcast unit tests with the fix: 244 run, 0 failures, 1
> error in
> {{HazelcastUserConfigSerializationFilterWarningTest.warnsForUserClientConfigWithoutFilter}}
> (a Hazelcast client cannot connect to the member in the test environment; it
> fails the same way on main).
> *How it was found*: reading the transacted consumer for transaction state
> held across threads, then a probe with an embedded member (the WARN above,
> and the three processed messages back in the queue after the member left),
> then the JUnit test above. Not run against a separate Hazelcast cluster.
> *Affected*: main, camel-4.23.x, camel-4.22.x, camel-4.18.x and camel-4.14.x
> (the same callback; read, not run).
> _Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)