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)