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

             Summary: camel-milo - the consumer never recovers when its 
subscription stops publishing (watchdog, Bad_Timeout)
                 Key: CAMEL-25691
                 URL: https://issues.apache.org/jira/browse/CAMEL-25691
             Project: Camel
          Issue Type: Improvement
          Components: camel-milo
            Reporter: Serdar Gökay


{{SubscriptionManager.SubscriptionListenerImpl}} implements only 
{{onTransferFailed}} (tears the connection down and rebuilds it) and 
{{onStatusChanged}} (logs at INFO). {{onWatchdogTimerElapsed}} keeps the no-op 
default of {{OpcUaSubscription.SubscriptionListener}}.

Consequence: when the server drops the subscription while the session stays 
alive (server-side subscription lifetime expired, server restarted with session 
reuse, subscription id no longer known), the publish response carries 
{{Bad_NoSubscription}} and Milo's {{PublishingManager}} stops sending publish 
requests for that subscription without reporting an error. Milo then fires the 
watchdog timer (publishing interval × (maxKeepAliveCount + 1) × 1.5) and leaves 
the reaction to the listener. Because our listener ignores it, the route keeps 
its last value forever: no exchange, no log line, no reconnect. A status change 
to {{Bad_Timeout}} (subscription timed out on the server) is logged at INFO and 
otherwise ignored for the same reason.

Why this matters: the consumer feeds historians, MES systems, Unified Namespace 
brokers and alarm handling, usually on unattended edge hosts. A subscription 
that silently stops is worse than a broken connection, because every downstream 
system keeps a stale value that still looks current. Industrial OPC UA clients 
treat the watchdog and {{Bad_Timeout}} as "recreate the subscription and its 
items" and report the loss, so an operator sees the gap instead of a frozen 
value.

Proposal:
* implement {{onWatchdogTimerElapsed}}: WARN with the subscription id, then 
recreate the subscription and its monitored items. The existing connection 
rebuild ({{handleConnectionFailure}}) already does this and is the simplest 
first version; a lighter "delete and recreate only this subscription" variant 
can follow if the rebuild proves too heavy.
* treat {{onStatusChanged}} with a bad status ({{Bad_Timeout}}, 
{{Bad_NoSubscription}}, {{Bad_SubscriptionIdInvalid}}) the same way, at WARN 
instead of INFO.
* a test with the embedded server that drops the subscription (or lets its 
lifetime expire) and asserts that values flow again without restarting the 
route.

The subscription's keep-alive and lifetime counts are left as they are; that is 
a separate topic.

I can send a PR.



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

Reply via email to