Serdar Gökay created CAMEL-25912:
------------------------------------

             Summary: camel-milo - client producers wait for the manager lock 
while a subscription service call holds it
                 Key: CAMEL-25912
                 URL: https://issues.apache.org/jira/browse/CAMEL-25912
             Project: Camel
          Issue Type: Improvement
          Components: camel-milo
            Reporter: Serdar Gökay


h3. Problem

{{SubscriptionManager}} uses one {{lock}} for the subscription work and for the 
producer requests. Registering monitored items, deactivating them when a route 
stops, recreating a subscription and, with CAMEL-25692, creating refused items 
again all hold {{lock}} across a blocking service call. The producer methods 
{{write}}, {{call}}, {{readValues}} and {{browse}}, and {{getOpcUaClient()}}, 
take the same {{lock}}, although under it they only read the current connection 
and start an asynchronous request. A producer request therefore waits, with its 
thread blocked, until the service call that holds {{lock}} completes:
* normally one round trip;
* during a silent network drop, until the keep-alive notices it. Against a real 
server with a refused node, a {{getOpcUaClient()}} call waited 9.8 s (see the 
review of [#28212|https://github.com/apache/camel/pull/28212]);
* with a server that answers the keep-alives but not the service call, up to 
the request timeout (60 s by default).

A write that sets a setpoint or sends a command then waits for unrelated 
subscription work on the same connection, for example another route that starts 
or stops.

h3. Proposal

The producer methods and {{getOpcUaClient()}} read the current connection 
without {{lock}} (a volatile field, still written under {{lock}}) and start 
their request as today. The subscription work keeps {{lock}}. Two things have 
to hold then:
# {{Connected.dispose()}} sets {{client}} to null. A request on a connection 
that is disposed meanwhile has to complete exceptionally, not with a 
NullPointerException.
# A failed request calls {{handleConnectionFailure}}, which tears down whatever 
connection is current. Without {{lock}} the failure may come from a connection 
that was replaced meanwhile, so it has to tear down only the connection the 
request was sent on.

For the second point it is worth deciding first whether a failed request should 
tear the connection down at all: Milo reactivates a lost session itself, and 
since CAMEL-25835 the consumers are told about the loss. If it should not, the 
second point goes away.

h3. Related

CAMEL-25694 and CAMEL-25695 
([#27956|https://github.com/apache/camel/pull/27956]) change the completion of 
the same four producer methods from {{handleAsync}} to {{whenCompleteAsync}}; 
this change would follow that one. Raised in the review of CAMEL-25692 
([#28212|https://github.com/apache/camel/pull/28212]).

I can send a PR.



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

Reply via email to