shashank created CAMEL-25846:
--------------------------------

             Summary: camel-tahu - after its route is restarted, an Edge Node 
producer never connects again and drops every message (logged, the exchange 
completes)
                 Key: CAMEL-25846
                 URL: https://issues.apache.org/jira/browse/CAMEL-25846
             Project: Camel
          Issue Type: Bug
          Components: camel-tahu
            Reporter: shashank
            Assignee: shashank


{{TahuEdgeProducer}} (main 20cdb309f7d0) keeps the {{TahuEdgeClient}} of each 
Edge Node in a static map ({{descriptorClients}}, {{computeIfAbsent}} in 
{{createClient}}). When the Edge Node producer stops, it shuts its client down 
({{TahuEdgeNodeProducer.doStop}}: {{tahuEdgeClient.shutdown()}}), but the 
client stays in the map.

A Tahu {{EdgeClient}} cannot run again after {{shutdown()}}: {{shutdown()}} 
sets {{stayRunning}} to false, only the constructor sets it to true, and 
{{run()}} returns at once when it is false (Tahu 1.0.21, read with javap). When 
the route is started again, Camel creates a new producer, whose constructor 
takes the shut down client from the map, and {{doStart}} submits it again 
({{TahuEdgeClient.startup()}}). The client never connects to the MQTT server 
again: the Edge Node stays offline (its NDEATH was the last message), and every 
message sent to the endpoint is dropped. {{EdgeClient.publishSparkplugMessage}} 
catches the failure and logs {{Failed to publish message on topic=...}} at 
ERROR, so the exchange completes without an exception. Device producers of the 
same Edge Node, also in routes that were not restarted, keep the old client 
too. This lasts until the JVM restarts (the map is static, so a new 
CamelContext in the same JVM takes the shut down client as well). A route 
restart is enough: stopping and starting the route (JMX, control bus, a route 
policy, a supervising route controller).

*Fix*: the Edge Node producer removes its client from the map when it stops 
(and shuts down the client's executor), and creates a new client when it 
starts. A new client gets the metric maps of the Edge Node and of its Devices 
again (kept in a static map by descriptor), and Device producers take the 
current client of their Edge Node when they publish. A Device producer never 
creates a client itself in that case.

*Tests*: new {{TahuEdgeProducerRestartTest}} (2 tests) with {{FakeMqttBroker}}, 
a small in-process MQTT 3.1.1 broker that acknowledges connections, 
subscriptions and publishes and records the published topics. 
{{edgeNodePublishesAgainAfterTheRouteIsRestarted}}: NBIRTH and one NDATA, stop 
and start the route, then a second NBIRTH and NDATA are expected. On main it 
fails: {{not published within 20 seconds; connects: 1, published: 
[spBv1.0/RestartGroup/NBIRTH/RestartNode, 
spBv1.0/RestartGroup/NDATA/RestartNode, 
spBv1.0/RestartGroup/DDEATH/RestartNode/D1, 
spBv1.0/RestartGroup/NDEATH/RestartNode]}}. 
{{deviceOfAnotherRoutePublishesAgainAfterTheEdgeNodeRouteIsRestarted}}: only 
the Edge Node route is restarted, and the Device route's DDATA is expected 
after the new DBIRTH; fails on main the same way ({{connects: 1}}). Both pass 
with the fix. camel-tahu unit tests with the fix: 9 run, 0 failures (the IT 
tests need a container and were not run).

*How it was found*: variant analysis of CAMEL-25838 (pattern: a client or 
connection that is shut down or replaced, while state that belongs to it, here 
the client in a static map and the Device metric maps, is kept or lost), then 
the JUnit tests.

*Affected*: main, camel-4.23.x, camel-4.18.x and camel-4.14.x (the same static 
map and shutdown; read, not run; the {{stayRunning}} behaviour was read in Tahu 
1.0.21 only).

_Filed with Claude Code on behalf of allthingssecurity._




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

Reply via email to