Skip to content

[NSJ -> STJ]Migrate AutoComplete#7298

Open
Nigusu-Allehu wants to merge 5 commits intodevfrom
dev-nyenework-autocomplete-stj
Open

[NSJ -> STJ]Migrate AutoComplete#7298
Nigusu-Allehu wants to merge 5 commits intodevfrom
dev-nyenework-autocomplete-stj

Conversation

@Nigusu-Allehu
Copy link
Copy Markdown
Member

@Nigusu-Allehu Nigusu-Allehu commented Apr 17, 2026

Bug

Fixes:
Related: NuGet/Home#14846

Description

Makes use of features introduced in #7313.

Replaces NSJ deserialization with (stj)JsonSerializer.DeserializeAsync into a new AutoCompleteModel POCO. STJ is now the default path. Users can opt back into NSJ by setting NUGET_USE_NSJ_DESERIALIZATION=true or via the NuGet.UseNSJDeserialization AppContext switch.

  • AutoCompleteModel - new internal POCO for STJ deserialization
  • NuGetFeatureFlags - new shared class with AppContext switch + env var opt-in for NSJ
  • AutoCompleteResourceV3 - dispatches to NSJ or STJ based on the flag; NSJ fallback is identical to the previous implementation
  • Tests cover both paths via a [Theory]

PR Checklist

  • Meaningful title, helpful description and a linked NuGet/Home issue
  • Added tests
  • Link to an issue or pull request to update docs if this PR changes settings, environment variables, new feature, etc.


var queryUri = queryUrl.Uri;
var results = await _client.GetJObjectAsync(
AutoCompleteModel results = await _client.ProcessStreamAsync(
Copy link
Copy Markdown

@richlander richlander Apr 17, 2026

Choose a reason for hiding this comment

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

I am surprised that AutoCompleteModel is always non-null. Is that correct?

Does this library not have nullable enabled?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not yet. It's #nullable disabled for now, but it's a work in progress

Comment thread src/NuGet.Core/NuGet.Protocol/Resources/AutoCompleteResourceV3.cs Outdated
var results = await _client.GetJObjectAsync(
AutoCompleteModel results = await _client.ProcessStreamAsync(
new HttpSourceRequest(queryUri, logger),
async stream =>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I don't know what the team code style is, if they link lamdas defined ahead of the method call or within it.

@Nigusu-Allehu Nigusu-Allehu self-assigned this Apr 18, 2026
@Nigusu-Allehu Nigusu-Allehu force-pushed the dev-nyenework-autocomplete-stj branch from 01dc4d3 to 6f4e797 Compare April 20, 2026 16:34
@Nigusu-Allehu Nigusu-Allehu marked this pull request as ready for review April 23, 2026 00:15
@Nigusu-Allehu Nigusu-Allehu requested a review from a team as a code owner April 23, 2026 00:15
@Nigusu-Allehu Nigusu-Allehu requested review from donnie-msft and jebriede and removed request for a team April 23, 2026 00:15
@Nigusu-Allehu Nigusu-Allehu changed the base branch from dev-feature-nsj-stj-migration to dev April 23, 2026 00:15
Comment thread test/NuGet.Core.Tests/NuGet.Protocol.Tests/AutoCompleteResourceV3Tests.cs Outdated
Comment thread test/NuGet.Core.Tests/NuGet.Protocol.Tests/AutoCompleteResourceV3Tests.cs Outdated
Comment thread build/Shared/NuGetFeatureFlags.cs Outdated

var queryUri = queryUrl.Uri;

if (NuGetFeatureFlags.UseNSJDeserializationFeatureSwitch || NuGetFeatureFlags.IsNSJDeserializationEnabledByEnvironment(_environmentVariableReader))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should learn from #7266, because this pattern here will read the environment variable every time, and on .NET Framework that causes memory allocations every time. Making it both testable and avoid allocations is difficult, but we need to find a solution.

When that other PR was open, I remember someone sharing an idea that EnvironmentVariableWrapper could cache values in a dictionary, so it avoids calling the BCL API that causes allocations after the first time. I don't love the idea because adding to static collections feels like a memory leak, but at the least the number of environment variables we check is low. If we can't find a better solution, then implementing this will be an easy fix.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This should have been caching. The idea was to pass null in production and the caching is done in the NuGetFeatureClassFlag class. And pass env value during test to avoid the caching.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Line 37 isn't using null, it's using EnvironmentVariableWrapper.Instance, so it's not going to cache. This shows a risk of this design. It's very prone to error, preventing caching. Even if you manually change it, I'm wondering if AI generated code is going to try to optimisticly keep using EnvironmentVariableWrapper.Instance since that's what's done in most other parts of the code.

From an API design point of view, the best APIs are hard or impossible to use wrong. So, fixing the null value is an option, but if we can find another design, we might be able to reduce risk of repeating the same error.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

To reduce the risk of future mistakes, I've added an XML docomment on IsLegacyJsonDeserializationEnabledByEnvironment that explicitly says to pass null in production for caching, and only pass a reader in tests. Since it's internal, we can revisit the design at any point during the migration if we find something cleaner.

Comment thread src/NuGet.Core/NuGet.Protocol/Resources/AutoCompleteResourceV3.cs Outdated
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