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

Work on CAMEL-26488 started by Andrea Cosentino.
------------------------------------------------
> camel-mina - sync producer always closes a timed-out session
> ------------------------------------------------------------
>
>                 Key: CAMEL-26488
>                 URL: https://issues.apache.org/jira/browse/CAMEL-26488
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-mina
>            Reporter: Andrea Cosentino
>            Assignee: Andrea Cosentino
>            Priority: Major
>             Fix For: 4.24.0
>
>
> The camel-mina synchronous producer ({{MinaProducer}} with {{sync=true}}) 
> writes a request to the MINA {{IoSession}} and then waits on a per-exchange 
> {{CountDownLatch}} ({{responseLatch}}) for the reply. A single inner 
> {{ResponseHandler}} ({{IoHandlerAdapter}}) stores the latest inbound message 
> in a field and counts down whichever {{responseLatch}} is current 
> ({{messageReceived}} then {{notifyResultAvailable}}). A sync producer is 
> non-singleton ({{isSingleton()}} returns false when sync is enabled), so it 
> is pooled and reused across exchanges.
> h3. Current behaviour
> When an exchange does not receive a reply within {{timeout}}, {{doProcess}} 
> calls {{maybeDisconnectOnTimeout()}} and throws 
> {{ExchangeTimedOutException}}. {{maybeDisconnectOnTimeout()}} currently 
> closes the session only when {{disconnectOnNoReply=true}} (the default).
> With {{disconnectOnNoReply=false}} a timed-out session is left open and 
> connected. Because the producer is pooled and reused, the next exchange 
> acquires the same producer, finds the session still open in {{doProcess}}, 
> and writes on it without reopening. If the peer then delivers the reply 
> belonging to the earlier (already timed-out) request, the shared 
> {{ResponseHandler.messageReceived}} stores that message and counts down the 
> current exchange's latch. The later exchange therefore completes successfully 
> with a message that was produced for the earlier request: there is no 
> correlation between an inbound reply and the request that is currently 
> waiting.
> The {{disconnectOnNoReply}} option is documented for the consumer only. The 
> {{MinaConfiguration.setDisconnectOnNoReply}} javadoc reads "If sync is 
> enabled then this option dictates MinaConsumer if it should disconnect where 
> there is no reply to send back." The producer honours the option as well, and 
> nothing documents that keeping a producer session open after a timeout lets a 
> stale reply be applied to a later exchange.
> h3. Behaviour after the change
> A synchronous producer always closes its session when a request times out, 
> regardless of {{disconnectOnNoReply}}, so a session whose peer still owes a 
> reply is never reused by a later exchange. The next exchange finds a closed 
> session and opens a fresh connection. The default behaviour 
> ({{disconnectOnNoReply=true}}) is unchanged.
> As a second layer, the {{ResponseHandler}} applies an inbound message to the 
> waiting exchange only when a matching request is actually in flight; a 
> message that arrives while no request is waiting, or that belongs to an 
> earlier request, is discarded instead of being returned as the current 
> exchange's result.
> h3. Classes involved
> * 
> {{components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaProducer.java}}
>  - {{doProcess}}, {{maybeDisconnectOnTimeout()}} and the inner 
> {{ResponseHandler}}.
> * 
> {{components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaConfiguration.java}}
>  - the {{setDisconnectOnNoReply}} javadoc.
> h3. Code-level change
> * {{maybeDisconnectOnTimeout()}} closes the producer session on timeout 
> unconditionally; previously it closed only when {{disconnectOnNoReply}} was 
> {{true}}. This continues the direction of CAMEL-17022, which introduced 
> {{maybeDisconnectOnTimeout()}}, and must not be reverted.
> * {{ResponseHandler}} gains an in-flight request guard (a request generation 
> set in {{doProcess}} before the write and captured by the handler) so 
> {{messageReceived}} applies a reply to the current exchange only when it 
> matches the waiting request, and otherwise discards it.
> * The {{MinaConfiguration.setDisconnectOnNoReply}} javadoc is updated to 
> state that the producer also uses the option and that a timed-out producer 
> session is now closed regardless of its value. Regenerate the catalog, 
> component-DSL and endpoint-DSL mirrors and {{mina-component.adoc}} if any 
> option metadata or description changes.
> * A functional note is added to 
> {{docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc}} on 
> {{main}} describing the changed producer-on-timeout behaviour.
> h3. Tests
> A new regression test under 
> {{components/camel-mina/src/test/java/org/apache/camel/component/mina/}} 
> (modelled on {{MinaDisconnectOnTimeOutTest}}): a sync producer with 
> {{disconnectOnNoReply=false}} runs two sequential InOut exchanges against a 
> test MINA TCP server that delays the first reply until the second request is 
> in flight (coordinated with latches, no {{Thread.sleep}}, using 
> {{MockEndpoint}} timed assertions or Awaitility per project conventions). The 
> test asserts that the second exchange does not complete with the first 
> exchange's reply - it either times out or receives only its own reply. The 
> existing {{MinaDisconnectOnTimeOutTest}} and the concurrent producer tests 
> remain green.



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

Reply via email to