[
https://issues.apache.org/jira/browse/CAMEL-25855?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18131400#comment-18131400
]
Claus Ibsen commented on CAMEL-25855:
-------------------------------------
Merged to main in https://github.com/apache/camel/pull/28378 (commit
76c81755f256), fixed in 4.24.0.
_Claude Code on behalf of davsclaus_
> camel-quickfix - an InOut request that times out or cannot be sent leaves its
> correlation rule and exchange in the engine for good
> ----------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-25855
> URL: https://issues.apache.org/jira/browse/CAMEL-25855
> Project: Camel
> Issue Type: Bug
> Components: camel-quickfix
> Reporter: shashank
> Assignee: shashank
> Priority: Major
> Fix For: 4.24.0
>
>
> For an InOut exchange, {{QuickfixjProducer.sendMessage}} registers a
> correlation rule (the exchange and its {{CorrelationCriteria}}) in the
> {{MessageCorrelator}} of the engine before it sends the FIX message, then
> waits for the reply up to {{CorrelationTimeout}} (default 1000 ms).
> {{MessageCorrelator}} removes a rule only in {{onEvent}}, when a message that
> matches its criteria arrives:
> {code:java}
> for (MessageCorrelationRule rule : rules) {
> if (rule.getMessageCriteria().evaluate(message)) {
> rule.setReplyMessage(message);
> rules.remove(rule);
> rule.getLatch().countDown();
> }
> }
> {code}
> So a rule stays registered for good, holding its exchange, when:
> * the wait times out and no matching message ever arrives (the counterparty
> answers with a session level Reject or a BusinessMessageReject that the
> criteria do not match, or does not answer at all);
> * the send fails: {{Session.send}} returns false (session not logged on, the
> producer throws {{CannotSendException}}) or throws. The exchange fails, so
> nobody waits for a reply (QuickFIX/J has stored an application message before
> it found the session not logged on, and may still resend it after the next
> logon).
> The rules are kept in a {{CopyOnWriteArrayList}} of the engine, which lives
> as long as the component, so they add up for every such request (a route that
> retries InOut sends while the session is down adds one per attempt). Each add
> copies the whole list, and every FIX message the engine receives or sends
> (application and admin messages, heartbeats) is evaluated against every
> leaked rule on the session thread.
> *Fix*: the waiting {{Callable}} removes its rule in a finally block (reply,
> timeout or interrupt), and the producer removes the rule of an exchange whose
> send failed (new {{MessageCorrelator.cancelReply(Exchange)}}). The rule is
> still registered before the send, so a fast reply is not missed.
> *Tests*: new {{QuickfixjProducerCorrelationCleanupTest}} (3 tests, same
> mocked session as {{QuickfixjProducerTest}}). On main:
> {{timedOutRequestsDoNotStayRegistered}} (50 InOut requests with a 10 ms
> timeout and no reply) fails with {{correlation rules left after 50 timed out
> requests ==> expected: <0> but was: <50>}};
> {{requestThatCannotBeSentDoesNotStayRegistered}} and
> {{requestWhoseSendThrowsDoesNotStayRegistered}} fail with {{expected: <0> but
> was: <1>}}. All pass with the fix. camel-quickfix unit tests with the fix: 46
> run, 0 failures (including the existing InOut tests of
> {{QuickfixjProducerTest}}).
> *How it was found*: a review of request/reply correlation in producers (where
> a waiting request is registered and where it is removed again). The JUnit
> tests above are the evidence; it was not run against a FIX counterparty.
> *Affected*: main, camel-4.23.x, camel-4.22.x, camel-4.18.x and camel-4.14.x
> (same {{MessageCorrelator}} and {{QuickfixjProducer}}; read, not run).
> _Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)