feat(opcua): configurable monitored-item queue size to retain queued values - #2715
Conversation
…values Adds a 'subscription-queue-size' connection option (default 1, so existing behavior is unchanged). When set >1: - change-of-state monitored items are sampled at the server's fastest rate (samplingInterval 0.0) so intermediate values accumulate between publishes; - the requested depth is used as the monitored item's queue size instead of the hard-coded 1; - onMonitoredValue fans DataChangeNotifications out without dropping duplicates: a single (name-keyed) event cannot hold two values for one tag, so the batch is flushed before a duplicate would overwrite it, keeping every queued value. With the default of 1 there is at most one value per item per publish, so the new paths are inert and behavior is byte-for-byte identical to before.
|
@tirsodelrey could it be that you based this on an old sha? |
There was a problem hiding this comment.
Pull request overview
Adds configurable OPC UA monitored-item queue depth to retain intermediate subscription values.
Changes:
- Adds the
subscription-queue-sizeoption. - Adjusts change-of-state sampling and monitored-item queue creation.
- Fans out queued data-change notifications without overwriting duplicate tags.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
OpcuaConfiguration.java |
Defines the queue-size option. |
OpcuaConnection.java |
Passes queue size into subscriptions. |
OpcuaSubscriptionHandle.java |
Configures sampling, queueing, and notification batching. |
OpcuaConfigurationTest.java |
Tests the configuration accessor. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
@sruehl Yes, it was branched from an older develop. I forgot to check for any updates before pushing. I've resolved the merge conflict, I hope it is OK now. |
|
sure, did you see the review comments? |
|
@sruehl Yes, Copilot is pretty spot on. I'm addressing these issues now and will push a commit ASAP. |
|
|
- validate the configured queue size against the OPC UA UInt32 range and reject out-of-range values up front, instead of failing later during message encoding; - apply the queue depth only to change-of-state monitored items; event and cyclic items keep queue size 1 (event notifications are fanned out through a name-keyed map that cannot retain duplicates, and cyclic items never sample faster than they publish); - test the queue-size option through ConfigurationFactory (default 1 and an explicit value) instead of setting the field reflectively.
…compatibility. Adding the queue-size parameter to the constructor had replaced the six-argument constructor instead of overloading, thus breaking compatibility with clients. Added a 3rd constructor that keeps a 6-arg signature
Summary
Adds a 'subscription-queue-size' connection option to the OPC UA driver, letting a subscription keep more than the latest value per monitored item beween publishes. Defaults to '1', so existing behavior is unchanged.
Motivation
For a change-of-state subscription, the server samples a monitored item and queues the values it observes between two publishes. Today the driver hard-codes the monitored-item queue size to
1withdiscardOldest = true, so only the most recent value survives each publish cycle, every intermediate change is dropped server-side before it ever reaches theclient. There is currently no way to capture those intermediate values (unless using a cyclic-type subscription)
This is only relevant when an item is sampled faster than the subscription publishes. With per-tag sampling already in place, a change-of-state tag can be told to sample at the server's fastest rate while still publishing at a fixed rate.
What changes
Behavior is gated on
subscription-queue-size > 1; with the default1nothing belowchanges.
@ConfigurationParameter("subscription-queue-size")(@LongDefaultValue(1)) onOpcuaConfiguration.samplingInterval = 0.0) so intermediate values actually accumulate in the queue between publishes. Tags with an explicit rate, cyclic tags, and event tags keep their current per-tag sampling.MonitoringParametersinstead of the hard-coded1.onMonitoredValueno longer collapses a publish into a single name-keyed event (which would overwrite when the same tag appears more than once, i.e. when the queue actually held multiple values). It accumulates a batch and flushes it as an event before a duplicate tag would overwrite, so every queued value is delivered. The common case (each tag once) still produces a single event.Backward compatibility
With
subscription-queue-size = 1(the default) there is at most one value per item per publish: the0.0-sampling branch is not taken, the queue size is1as before, and the fan-out produces exactly one eventNotes
The effective depth is bounded by the server's
RevisedQueueSize; a server may cap the requested size (e.g. to 2). The driver delivers whatever the server actually queues without dropping; anything beyond the revised depth is discarded server-side (discardOldest).