Skip to content

Conversation

pranavkm
Copy link
Contributor

@pranavkm pranavkm commented Mar 17, 2021

  • Host a Roslyn workspace to produce EnC deltas and apply to app
  • Add agents for ASP.NET Core and Blazor WebAssembly apps

@ghost
Copy link

ghost commented Mar 17, 2021

I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label.

@pranavkm pranavkm force-pushed the prkrishn/hot-reload branch from 5d68ec1 to 1395942 Compare March 17, 2021 17:25
@pranavkm pranavkm added the Area-AspNetCore RazorSDK, BlazorWebAssemblySDK, dotnet-watch label Mar 17, 2021
@pranavkm pranavkm force-pushed the prkrishn/hot-reload branch 3 times, most recently from 216dc0c to 05126e0 Compare March 17, 2021 23:12
* Host a Roslyn workspace to produce EnC deltas and apply to app
* Add "agents" to support reloading ASP.NET Core and Blazor WebAssembly apps
@pranavkm
Copy link
Contributor Author

I was hoping we could yolo this change for preview3, and I can do a walkthru of this next week. There's some design issues that might be nice to get some ideas on, plus it would be good if we can have others follow what's happening here.

@pranavkm pranavkm requested a review from wli3 March 18, 2021 01:49
@pranavkm
Copy link
Contributor Author

@wli3 since this involves a changes to the redist, NuGet.config and the version files.

foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var customAttributes = assembly.GetCustomAttributes<AssemblyMetadataAttribute>();
var deltaReceiverAttributes = customAttributes.Where(a => a.Key == "ReceiveHotReloadDeltaNotification" && !string.IsNullOrEmpty(a.Value));
Copy link
Member

Choose a reason for hiding this comment

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

Who is responsible for applying the ReceiveHotReloadDeltaNotification on the app's assemblies. The compiler?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will eventually get replaced by a runtime API: dotnet/runtime#49361. This is a place holder until those APIs come online.

}
catch (TimeoutException)
{
Log("Unable to connect to hot-reload server.");
Copy link
Member

Choose a reason for hiding this comment

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

Does the hot-reload server log out info that would help determine why it failed to connect here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Running watch --verbose should emits a fair bit of the diagnostics (for instance if the named pipe is in use), so that should probably help piecing this together.

}
}

// We want to base this off of mvids, but we'll figure that out eventually.
Copy link
Member

Choose a reason for hiding this comment

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

As in eventually we'll be doing something like update.ChangedMvid?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup. Right now it's an empty collection, but it's a hypothetical idea I'd been playing around with to do different things based on what function gets updated.

location.reload();
return;
}
if (parsed.type == 'UpdateStaticFile') {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: might be time for a switch statement here.

context.ProcessSpec.EnvironmentVariables.DotNetStartupHooks.Add(deltaApplier);

// Configure the app for EnC
context.ProcessSpec.EnvironmentVariables["DOTNET_MODIFIABLE_ASSEMBLIES"] = "debug";
Copy link
Member

Choose a reason for hiding this comment

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

What values can DOTNET_MODIFIABLE_ASSEMBLIES have?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it's the only possible value for it: dotnet/runtime#47274

{
if (_deltaApplier is null)
{
_deltaApplier = context.DefaultLaunchSettingsProfile.HotReloadProfile == "blazorwasm" ?
Copy link
Member

Choose a reason for hiding this comment

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

How do things get set up for a hosted Blazor WASM app?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

await _pipe.FlushAsync(cancellationToken);

var result = ApplyResult.Failed;
var bytes = ArrayPool<byte>.Shared.Rent(1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems unnecessary to rent an array of size 1 here. I'd bet the array returned will be size 4096. If only one call to Apply is being run at a time, you could have it in a field.

{
// FSW events sometimes appear before the file has been completely written to disk. Provide a small delay before we read the file contents
// to ensure we are not contending with partial writes or write locks.
await Task.Delay(20);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the goal here to maximize the chance of the first call succeeding?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup. This is obviously very twitchy, but so far it seems to work. I should remove the Task.Delay and see if I can make this work.


if (!fileSet.Project.IsNetCoreApp60OrNewer())
{
_reporter.Error($"Hot reload based watching is only supported in .NET 6.0 or newer apps. Update the project's launchSettings.json to disable this feature.");
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems bad. Are you saying that anyone who has a mix of projects (5.0, 6.0) will need to manually go into their launchsettings.json to disable it? Could it be a property in the csproj instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The launching project must be a net6 project since the APIs to apply hot reload are only available in net6.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we make this fail earlier for 5.0 and earlier?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You have to explicitly modify the launchSettings to enable hot reload. So it's a bit unusual to get in a bad state to begin with. This is the earliest we know of their tfm.

Base automatically changed from master to main March 18, 2021 21:05
Copy link
Member

@captainsafia captainsafia left a comment

Choose a reason for hiding this comment

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

:shipit:

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

Labels

Area-AspNetCore RazorSDK, BlazorWebAssemblySDK, dotnet-watch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants