Skip to content

DYN-10081: Preserve warnings/info stack format and Batch node info updates#16955

Merged
zeusongit merged 5 commits into
DynamoDS:masterfrom
zeusongit:10081
Apr 1, 2026
Merged

DYN-10081: Preserve warnings/info stack format and Batch node info updates#16955
zeusongit merged 5 commits into
DynamoDS:masterfrom
zeusongit:10081

Conversation

@zeusongit

Copy link
Copy Markdown
Contributor

Purpose

TL;DR
Fixes a bug where Info and Warning bubbles couldn't coexist on non-chart nodes (info would silently wipe the warning from the Infos collection), plus performance and lifecycle improvements to the bubble system.

Problem

  • Info supersedes Warning on non-chart nodes — When Info() is called after Warning(), the state restoration in Info() triggers ClearTransientWarningsAndErrors() as a side effect of the State setter, wiping the Warning entry from Infos. Chart nodes don't hit this because they use persistent variants.
  • O(n²) event cascade in bubble updates — Each NodeMessages.Add() triggers a full RefreshNodeInformationalStateDisplay() rebuild (clears and repopulates 3 display collections with ~30 events each). For N messages, this means N full rebuilds per update.
  • ClearInfoMessages() could accidentally demote Warning/Error states — Setting State = Active unconditionally triggered the setter side effect, clearing transient warnings.
  • Info.GetHashCode() operator precedence bug — Missing parentheses caused the hash seed to be discarded and null Message to throw NRE.

Changes

  • Added suppressTransientClear flag to prevent Info() state restoration from triggering ClearTransientWarningsAndErrors(). Now Warning+Info entries coexist in Infos and both render in the bubble, stacked like chart nodes.
  • ClearInfoMessages() no longer unconditionally sets State = Active. Added fallthrough else branch for when State doesn't match Info/PersistentInfo.
  • Fixed GetHashCode() precedence: hash * 23 + (Message == null ? 0 : Message.GetHashCode()).
  • Moved all 5 event subscriptions inside if (ErrorBubble == null) guard in BuildErrorBubble() to prevent potential double-subscription. Added Contains check before Errors.Add.
  • Added batchUpdateDepth counter with BeginBatchUpdate()/EndBatchUpdate() (nesting-safe).

What this enables

All three bubble sections (Error, Warning, Info) can now coexist on any node — not just chart nodes. The node's bottom bar reflects the highest-priority state, and the bubble stacks sections vertically: Errors (red) → Warnings (orange) → Info (blue).

Before:
Screenshot 2026-03-11 133259

After:
Screenshot 2026-03-11 152617

Declarations

Check these if you believe they are true

Release Notes

Fixed a bug where Info and Warning bubbles couldn't coexist on non-chart nodes (info would silently wipe the warning from the Infos collection), plus performance and lifecycle improvements to the bubble system.

Reviewers

(FILL ME IN) Reviewer 1 (If possible, assign the Reviewer for the PR)

(FILL ME IN, optional) Any additional notes to reviewers or testers.

FYIs

(FILL ME IN, Optional) Names of anyone else you wish to be notified of

Prevent transient warnings/errors from being cleared when restoring node State during Info() by adding a suppressTransientClear flag and scoping State assignments. Adjust ClearInfoMessages so only info-related states are promoted back to Active and other states (Warning/Error) keep their state while still removing info entries. Add batching to InfoBubble/NodeViewModel updates (BeginBatchUpdate/EndBatchUpdate and dispatcher invocation) to avoid repeated RefreshNodeInformationalStateDisplay calls and duplicate subscriptions/Workspace error entries. Minor fixes: tighten GetHashCode parentheses and add Clear() to ObservableHashSet. Overall: correctness (preserve warnings) and performance (batch updates, avoid double-subscribe).
@zeusongit
zeusongit requested review from a team and Copilot March 11, 2026 19:44

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the ticket for this pull request: https://jira.autodesk.com/browse/DYN-10081

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes and improves the node “bubble” messaging system so Info and Warning/Error bubbles can coexist (stacked) on non-chart nodes, while also reducing redundant UI refresh work during message updates.

Changes:

  • Prevents NodeModel.Info() state restoration from clearing transient warnings/errors, allowing Warning+Info to coexist in Infos.
  • Adds batching to suppress per-item RefreshNodeInformationalStateDisplay() rebuilds during NodeMessages updates.
  • Improves bubble lifecycle/subscription handling and fixes Info.GetHashCode() operator precedence.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/DynamoUtilities/ObservableHashSet.cs Adds Clear() with collection reset notification support.
src/DynamoCoreWpf/ViewModels/Preview/InfoBubbleViewModel.cs Adds nested batch update tracking to suppress repeated refresh during bulk NodeMessages updates; disposes more cleanly.
src/DynamoCoreWpf/ViewModels/Core/NodeViewModel.cs Batches bubble message updates, prevents duplicate subscriptions, avoids duplicate Errors insertion, and nulls ErrorBubble on dispose.
src/DynamoCore/Graph/Nodes/NodeModel.cs Fixes GetHashCode(), adds suppression flag for state restoration side-effects, and updates ClearInfoMessages() / Info() behavior.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread src/DynamoCore/Graph/Nodes/NodeModel.cs Outdated
Comment thread src/DynamoCoreWpf/ViewModels/Preview/InfoBubbleViewModel.cs
Comment thread src/DynamoCore/Graph/Nodes/NodeModel.cs Outdated
Comment thread src/DynamoCore/Graph/Nodes/NodeModel.cs Outdated
Comment thread src/DynamoCore/Graph/Nodes/NodeModel.cs
// For any other state (Warning, Error, Active, Dead, etc.), clear all info types.
// This fixes the case where State was restored (e.g., by Info() method) and no
// longer matches Info/PersistentInfo, but info entries still exist in Infos.
infos.RemoveWhere(x => x.State == ElementState.PersistentInfo || x.State == ElementState.Info);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This confusing naming has been there for a while. We have a notion of Info vs Warning messages, but we still maintain a type with the same conflicting name, "Info", that actually can be any type of message, even warning or error.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a good time to rename some of these fields/properties to something more sensible and have a clear separation of meaning?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will look into this, this has bothered me for a while too

CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, range));
}

public void Clear()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this new method called?

@aparajit-pratap aparajit-pratap left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments and questions, then LGTM!

Rename the private boolean suppressTransientClear to suppressClearTransientMessages in NodeModel and update all references accordingly. The flag is used to suppress clearing transient warnings/errors during state/Info restoration. Also remove the public Clear() method from ObservableHashSet<T> (and its Reset event invocation), so the collection no longer exposes a Clear API.
@sonarqubecloud

Copy link
Copy Markdown

@zeusongit

Copy link
Copy Markdown
Contributor Author

Some minor comments and questions, then LGTM!

PTAL

@zeusongit
zeusongit requested review from a team and aparajit-pratap March 31, 2026 22:21
@zeusongit zeusongit added this to the 4.1 milestone Apr 1, 2026
@zeusongit
zeusongit merged commit 238d2a5 into DynamoDS:master Apr 1, 2026
28 of 29 checks passed
github-actions Bot pushed a commit that referenced this pull request Apr 1, 2026
@github-actions

github-actions Bot commented Apr 1, 2026

Copy link
Copy Markdown

Successfully created backport PR for RC4.1.0_master:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants