shashank created CAMEL-24948:
--------------------------------

             Summary: camel-seda - SedaProducer swallows InterruptedException 
and reports success: message not queued, or the request returned as the reply
                 Key: CAMEL-24948
                 URL: https://issues.apache.org/jira/browse/CAMEL-24948
             Project: Camel
          Issue Type: Bug
          Components: camel-seda
            Reporter: shashank


{{SedaProducer}} catches {{InterruptedException}}, re-sets the interrupt flag 
and carries on as if the send had worked:
* {{addToQueue}} with {{blockWhenFull=true}} ({{queue.put}}, 
SedaProducer.java:237-243).
* {{addToQueue}} with {{blockWhenFull=true&offerTimeout=...}} ({{queue.offer}}, 
:244-256, commented {{// ignore}}).
* Request/reply with {{timeout<=0}} ({{latch.await()}}, :141-145).

{{process()}} then calls {{callback.done(true)}} without setting an exception, 
so the caller is told the send succeeded:
* *InOnly:* the message is not in the queue and is lost.
* *InOut with timeout<=0:* the caller gets back its own request as the "reply". 
The real reply is later copied into that exchange when the consumer finishes.

Reproduced against 4.23.0-SNAPSHOT (the caller thread is interrupted while it 
waits):
{noformat}
InOnly to seda:full?size=1&blockWhenFull=true (queue full)      -> 
exception=null, queue=[m1]   (m2 lost)
InOnly to seda:full2?size=1&blockWhenFull=true&offerTimeout=5000 -> 
exception=null, queue=[m1]   (m2 lost)
InOut  to seda:slow?timeout=0                                   -> 
body=request, exception=null
{noformat}
Camel interrupts such threads itself when a route stop hits its timeout and the 
consumer's thread pool is shut down with {{shutdownNow}}. Route {{seda:up -> 
to(seda:down?size=1&blockWhenFull=true)}}, with the {{down}} queue full, 
stopped with a 1 s timeout: the step after {{to(seda:down...)}} ran with 
{{exception=null}}, and the message was never put in {{down}}. An upstream 
transactional or acknowledging consumer would commit/ack such a message.

The non-blocking paths already fail the exchange ("Queue full" 
{{IllegalStateException}}, and the {{offerTimeout}} "Fails to insert element 
into queue" exception), so only the interrupted paths report a false success.

Proposed fix: keep re-setting the interrupt flag, but fail the exchange:
* {{addToQueue}}, when interrupted in {{put}} ({{blockWhenFull}}), in 
{{offer(offerTimeout)}} and in the {{discardWhenFull}} {{offer(0)}} (which 
throws when the interrupt flag is already set): throw a 
{{RejectedExecutionException("Interrupted while adding the exchange to the 
queue")}} with the {{InterruptedException}} as cause. It surfaces to the caller 
like the existing "Queue full" / "Fails to insert element into queue" 
exceptions.
* Reply wait with {{timeout<=0}}, when interrupted: set the 
{{InterruptedException}} on the exchange (as {{DirectProducer}} does), remove 
the copy from the queue if it is still there, and make a later reply be ignored 
(as on timeout).
* The interrupted *timed* reply wait already fails with 
{{ExchangeTimedOutException}}; unchanged.

A PR with the fix follows, with regression test 
{{SedaProducerInterruptedTest}}, plus an upgrade-guide note. Regarding 
CAMEL-22390 ("do not interrupt Camel threads"): Camel interrupts these threads 
itself when a route stop is forced after the shutdown timeout (case D above).



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to