@@ -305,9 +305,7 @@ private void transferTabletRowForClientServerModel(
305305 new DateTime (utcTimestamp ),
306306 new DateTime ());
307307 measurementNode = addNode (name , currentFolder , folderNode , dataValue , type );
308- if (Objects .isNull (measurementNode .getValue ())
309- || Objects .isNull (measurementNode .getValue ().getSourceTime ())
310- || measurementNode .getValue ().getSourceTime ().getUtcTime () < utcTimestamp ) {
308+ if (shouldNotifyNodeValueChange (measurementNode , utcTimestamp )) {
311309 notifyNodeValueChange (measurementNode .getNodeId (), dataValue , measurementNode );
312310 }
313311 } else {
@@ -325,9 +323,7 @@ private void transferTabletRowForClientServerModel(
325323 new DataValue (
326324 new Variant (value ), currentQuality , new DateTime (timestamp ), new DateTime ()),
327325 dataType );
328- if (Objects .isNull (valueNode .getValue ())
329- || Objects .isNull (valueNode .getValue ().getSourceTime ())
330- || valueNode .getValue ().getSourceTime ().getUtcTime () < timestamp ) {
326+ if (shouldNotifyNodeValueChange (valueNode , timestamp )) {
331327 notifyNodeValueChange (
332328 valueNode .getNodeId (),
333329 new DataValue (
@@ -337,6 +333,26 @@ private void transferTabletRowForClientServerModel(
337333 }
338334 }
339335
336+ private boolean shouldNotifyNodeValueChange (
337+ final UaVariableNode variableNode , final long candidateUtcTime ) {
338+ final DataValue currentValue = variableNode .getValue ();
339+ if (Objects .isNull (currentValue ) || Objects .isNull (currentValue .getSourceTime ())) {
340+ return true ;
341+ }
342+ final long currentUtcTime = currentValue .getSourceTime ().getUtcTime ();
343+ if (currentUtcTime < candidateUtcTime ) {
344+ return true ;
345+ }
346+ if (candidateUtcTime < currentUtcTime ) {
347+ LOGGER .debug (
348+ "Reject stale value update: nodeId={}, candidateSourceTime={}, currentSourceTime={}." ,
349+ variableNode .getNodeId (),
350+ candidateUtcTime ,
351+ currentUtcTime );
352+ }
353+ return false ;
354+ }
355+
340356 private UaVariableNode addNode (
341357 final String nodeName ,
342358 final String currentFolder ,
@@ -639,14 +655,19 @@ public void onDataItemsCreated(final List<DataItem> dataItems) {
639655 final NodeId nodeId = readValueId .getNodeId ();
640656
641657 // 1. Add the new subscription item to the subscription mapping
642- nodeSubscriptions .compute (
658+ final List <DataItem > subscribedItems =
659+ nodeSubscriptions .compute (
660+ nodeId ,
661+ (k , existingList ) -> {
662+ List <DataItem > list =
663+ existingList != null ? existingList : new CopyOnWriteArrayList <>();
664+ list .add (item );
665+ return list ;
666+ });
667+ LOGGER .debug (
668+ "Registered data item subscription: nodeId={}, subscriptionCount={}." ,
643669 nodeId ,
644- (k , existingList ) -> {
645- List <DataItem > list =
646- existingList != null ? existingList : new CopyOnWriteArrayList <>();
647- list .add (item );
648- return list ;
649- });
670+ subscribedItems .size ());
650671
651672 // 2. 【Key Optimization】Proactively push the current node's initial value when the new
652673 // subscription item is created
@@ -680,13 +701,18 @@ public void onDataItemsDeleted(final List<DataItem> dataItems) {
680701 final NodeId nodeId = readValueId .getNodeId ();
681702
682703 // When the client cancels the subscription, remove this subscription item from the mapping
683- nodeSubscriptions .computeIfPresent (
704+ final List <DataItem > remainingItems =
705+ nodeSubscriptions .computeIfPresent (
706+ nodeId ,
707+ (k , existingList ) -> {
708+ existingList .remove (item );
709+ // Automatically clean up the key when there are no subscribers, save memory
710+ return existingList .isEmpty () ? null : existingList ;
711+ });
712+ LOGGER .debug (
713+ "Removed data item subscription: nodeId={}, subscriptionCount={}." ,
684714 nodeId ,
685- (k , existingList ) -> {
686- existingList .remove (item );
687- // Automatically clean up the key when there are no subscribers, save memory
688- return existingList .isEmpty () ? null : existingList ;
689- });
715+ Objects .isNull (remainingItems ) ? 0 : remainingItems .size ());
690716 }
691717 }
692718
0 commit comments