From bca3348c1abc91a502dbc6b81061acdc8626896f Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Sat, 13 Jul 2024 10:04:25 +1000 Subject: [PATCH] Fix hang in Solution Explorer search through transitive package items of dependencies tree (#5917) * Revert "Reduce number of Dataflow updates through dependency tree code (#5508)" This reverts commit d85c6ea4588c5b4f2b4a4d7bf8073837fb308f58. Turns out that the search provider uses `GetLatestVersionAsync` on this data source, meaning it must propagate a value for every input version. I will fix the original issue in a different way, by updating the consumer to ignore version-only changes instead. * Avoid tree updates when the value is unchanged This replaces the approach taken in #5508 in a way that doesn't interfere with Solution Explorer search. --- .../AssetsFileDependenciesDataSource.cs | 21 ++++++------------- ...velDependenciesCollectionSourceProvider.cs | 10 +++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/SolutionExplorer/AssetsFileDependenciesDataSource.cs b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/SolutionExplorer/AssetsFileDependenciesDataSource.cs index 402614818f2..0a545137c86 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/SolutionExplorer/AssetsFileDependenciesDataSource.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/SolutionExplorer/AssetsFileDependenciesDataSource.cs @@ -4,7 +4,6 @@ #nullable enable using System; -using System.Collections.Generic; using System.ComponentModel.Composition; using System.IO; using System.Threading.Tasks.Dataflow; @@ -39,7 +38,7 @@ protected override IDisposable LinkExternalInput(ITargetBlock>( @@ -49,7 +48,7 @@ IReceivableSourceBlock> proje = _activeConfiguredProjectSubscriptionService.ProjectRuleSource.SourceBlock; IPropagatorBlock>, IProjectVersionedValue> transformBlock - = DataflowBlockSlim.CreateTransformManyBlock>, IProjectVersionedValue>(Transform, skipIntermediateInputData: true, skipIntermediateOutputData: true); + = DataflowBlockSlim.CreateTransformBlock>, IProjectVersionedValue>(Transform, skipIntermediateInputData: true, skipIntermediateOutputData: true); return new DisposableBag { @@ -76,7 +75,7 @@ IPropagatorBlock> Transform(IProjectVersionedValue> update) + IProjectVersionedValue Transform(IProjectVersionedValue> update) { var projectSnapshot = (IProjectSnapshot2)update.Value.Item1; IProjectSubscriptionUpdate subscriptionUpdate = update.Value.Item2; @@ -84,7 +83,7 @@ IEnumerable> Transform(IP string? path = null; DateTime timestampUtc = DateTime.MinValue; - AssetsFileDependenciesSnapshot? snapshot = lastSnapshot; + AssetsFileDependenciesSnapshot snapshot = lastSnapshot; if (subscriptionUpdate.CurrentState.TryGetValue(ConfigurationGeneralRule.SchemaName, out IProjectRuleSnapshot ruleSnapshot)) { @@ -116,21 +115,13 @@ IEnumerable> Transform(IP lastAssetsFilePath = path; lastTimestampUtc = timestampUtc; - snapshot ??= AssetsFileDependenciesSnapshot.Empty; - - lastSnapshot = snapshot = snapshot.UpdateFromAssetsFile(path); - - yield return new ProjectVersionedValue(snapshot, update.DataSourceVersions); + lastSnapshot = snapshot = lastSnapshot.UpdateFromAssetsFile(path); } } } } - if (lastSnapshot is null) - { - lastSnapshot = AssetsFileDependenciesSnapshot.Empty; - yield return new ProjectVersionedValue(lastSnapshot, update.DataSourceVersions); - } + return new ProjectVersionedValue(snapshot, update.DataSourceVersions); } } } diff --git a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/SolutionExplorer/AssetsFileTopLevelDependenciesCollectionSourceProvider.cs b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/SolutionExplorer/AssetsFileTopLevelDependenciesCollectionSourceProvider.cs index 76fc6882f73..eda8de9e5fa 100644 --- a/src/NuGet.Clients/NuGet.VisualStudio.Implementation/SolutionExplorer/AssetsFileTopLevelDependenciesCollectionSourceProvider.cs +++ b/src/NuGet.Clients/NuGet.VisualStudio.Implementation/SolutionExplorer/AssetsFileTopLevelDependenciesCollectionSourceProvider.cs @@ -92,11 +92,21 @@ protected override bool TryCreateCollectionSource( var collectionSource = new AggregateRelationCollectionSource(hierarchyItem); AggregateContainsRelationCollection? collection = null; + AssetsFileDependenciesSnapshot? lastSnapshot = null; var actionBlock = new ActionBlock>( async versionedValue => { AssetsFileDependenciesSnapshot snapshot = versionedValue.Value; + + if (ReferenceEquals(snapshot, lastSnapshot)) + { + // Skip version-only updates. + return; + } + + lastSnapshot = snapshot; + if (snapshot.TryGetTarget(target, out AssetsFileTarget? targetData)) { if (TryGetLibrary(targetData, libraryName, out AssetsFileTargetLibrary? library))