etzel-mes commented on code in PR #27910:
URL: https://github.com/apache/camel/pull/27910#discussion_r4287647723
##########
components/camel-milo/src/main/java/org/apache/camel/component/milo/client/internal/SubscriptionManager.java:
##########
@@ -683,6 +697,37 @@ public OpcUaClient getOpcUaClient() {
}
}
+ /**
+ * Deletes and creates the subscription of the current connection again,
inside the existing session, and creates
+ * its monitored items again. Does nothing if the subscription no longer
belongs to the current connection or has
+ * already been recreated since the given id was observed. Falls back to
rebuilding the connection if this fails.
+ */
+ private void recreateSubscription(final OpcUaSubscription subscription,
final Optional<UInteger> id) {
+ lock.lock();
+ try {
+ if (this.disposed || this.connected == null ||
this.connected.manager != subscription
+ || !subscription.getSubscriptionId().equals(id)) {
+ LOG.debug("Subscription {} is stale or already recreated",
id.orElse(null));
+ return;
+ }
+ try {
+ subscription.delete();
+ } catch (final UaException e) {
+ LOG.debug("Failed to delete subscription {}", id.orElse(null),
e);
+ subscription.reset();
+ }
Review Comment:
Agreed. With a closed connection it was worse than an orphan: the `reset()`
and `create()` that followed waited for the session while holding `lock`, and
with a producer on the connection that never ended (details in the main
comment). The new version has no `reset()`. It creates the subscription again
only when `deleteAsync()` returns `Good` or `Bad_SubscriptionIdInvalid`, that
is, after Milo has reset the object itself in `applyDeleteResponse`. A lost
connection or session is left to Milo's session recovery, and any other
failure, such as a request timeout, rebuilds the connection through
`handleConnectionFailure`, which closes the session together with the
subscription. The `Bad_Timeout` path goes through the same code; there the
delete completes without a service call, as you say.
_Claude Code on behalf of etzel-mes_
##########
components/camel-milo/src/main/java/org/apache/camel/component/milo/client/internal/SubscriptionManager.java:
##########
@@ -683,6 +697,37 @@ public OpcUaClient getOpcUaClient() {
}
}
+ /**
+ * Deletes and creates the subscription of the current connection again,
inside the existing session, and creates
+ * its monitored items again. Does nothing if the subscription no longer
belongs to the current connection or has
+ * already been recreated since the given id was observed. Falls back to
rebuilding the connection if this fails.
+ */
+ private void recreateSubscription(final OpcUaSubscription subscription,
final Optional<UInteger> id) {
+ lock.lock();
+ try {
+ if (this.disposed || this.connected == null ||
this.connected.manager != subscription
+ || !subscription.getSubscriptionId().equals(id)) {
+ LOG.debug("Subscription {} is stale or already recreated",
id.orElse(null));
+ return;
+ }
+ try {
+ subscription.delete();
+ } catch (final UaException e) {
+ LOG.debug("Failed to delete subscription {}", id.orElse(null),
e);
+ subscription.reset();
+ }
+ subscription.create();
+ if
(!subscription.createMonitoredItems().stream().allMatch(MonitoredItemServiceOperationResult::isGood))
{
+ throw new UaException(StatusCodes.Bad_UnexpectedError, "Failed
to create the monitored items again");
+ }
Review Comment:
Done. The recreate clears `goodSubscriptions`, drops the monitored items
that were reset with the subscription, and passes the subscriptions it held to
`putSubscriptions`, so `goodSubscriptions` is rebuilt from the results. A node
that cannot be monitored again is removed from the subscription and from
`goodSubscriptions`, and is reported once to its consumer as a bad `DataValue`
after `lock` has been released. Only a failed `create()` or a rejected service
call rebuilds the connection.
`nodeThatCannotBeMonitoredAgainIsReportedWithoutRebuildingTheConnection`
deletes one of two monitored nodes on the embedded server before the
subscription times out there, and checks that its consumer receives
`Bad_NodeIdUnknown`, that the other node keeps delivering and that the
`OpcUaClient` is the same instance. It fails with the first revision, which
rebuilt the connection.
_Claude Code on behalf of etzel-mes_
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]