[ 
https://issues.apache.org/jira/browse/CAMEL-26856?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Claus Ibsen updated CAMEL-26856:
--------------------------------
    Fix Version/s: 4.24.0

> camel-kafka - exactlyOnce: a Kafka send whose retry was rejected, in a route 
> called from a doTry, is replayed after the doCatch instead of skipped
> --------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-26856
>                 URL: https://issues.apache.org/jira/browse/CAMEL-26856
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-kafka
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>             Fix For: 4.24.0
>
>
> With {{exactlyOnce}} on a Kafka consumer, the route calls another route from 
> a {{doTry}} block (for example with {{direct}}), and that route sends to 
> Kafka with an error handler that redelivers ({{maximumRedeliveries}} > 0). 
> When the send fails, its retry is rejected inside the open transaction: 
> {{KafkaProducer}} (around line 709-726) sets {{rollbackOnly}} and the 
> {{CamelKafkaExactlyOnceRetryRollback}} property, and throws. The called route 
> fails unhandled, the {{doCatch}} of the calling route catches the failure, 
> and {{CatchProcessor}} sets {{rollbackOnly}} again after the {{doCatch}} 
> block.
> {{KafkaTransactionSynchronization.onDone}} skips the rollback of such a 
> rejected retry only when the exchange is failure handled 
> ({{handledRedeliveryRejection}}, lines 123-125 and 142-143). Since 
> CAMEL-26447 the exchange is no longer marked failure handled after a 
> {{doCatch}} caught the failure of a called route, as when the {{doTry}} fails 
> in the route itself. So the source transaction is aborted and the source 
> record is replayed, where before CAMEL-26447 it took the offsets-only path 
> (abort the output, commit the source offsets, skip the record). For a send 
> that keeps failing (for example a record that is too large), every replay 
> ends the same way, so the consumer does not get past that record.
> A {{doTry}} that fails in the route itself is not affected: no redelivery 
> runs inside the {{doTry}}, so no retry is rejected, and the recorded send 
> failure takes the offsets-only path.
> Expected: a rejected retry whose failure was handled, by an error handler or 
> by a {{doCatch}}, takes the offsets-only path, as before CAMEL-26447 and as 
> for a {{doTry}} that fails in the route.
> Possible fix, in camel-kafka: treat the rejected retry as handled when the 
> exchange has no exception left, instead of requiring the failure handled mark:
> {code:java}
> boolean handledRedeliveryRejection = exchange.getException() == null
>         && 
> Boolean.TRUE.equals(exchange.getProperty(KafkaExactlyOnceMetadata.RETRY_ROLLBACK_PROPERTY));
> {code}
> A rejection that nothing handled keeps its exception and is still rolled back 
> by the branch on {{exchange.getException() != null}}. A rollback that the 
> route asks for itself after the rejection ({{markRollbackOnly}}) is not told 
> apart from the rejection, which is already the case today when an error 
> handler handled it.
> Test: a variant of 
> {{KafkaTransactionSynchronizationTest.handledInTransactionRedeliveryRejectionCommitsOffsetsAfterAbortingOutput}}
>  with {{isFailureHandled()}} returning false (the {{doCatch}} case), and if 
> practical a case in {{KafkaExactlyOnceIT}} with the {{doTry}} calling a route 
> that redelivers a failing send.
> CAMEL-26447 exposes this, so it should be fixed in the same release (4.24.0). 
> Found in the review of CAMEL-26447 (apache/camel#29584), from reading the 
> code; not reproduced with a broker.
> _Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to