Skip to content

Ensure DI scope is disposed #11894

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 5, 2019
Merged

Conversation

SteveSandersonMS
Copy link
Member

Fixes #11848. Addresses the two cases from that issue:

  • If a circuit handler throws
  • If prerendering throws

@SteveSandersonMS SteveSandersonMS added the area-blazor Includes: Blazor, Razor Components label Jul 4, 2019

namespace Microsoft.AspNetCore.Components.Server.Circuits
{
internal class CircuitPrerenderer : IComponentPrerenderer
{
private static object CircuitHostKey = new object();
private static object NavigationStatusKey = new object();
private static object CancellationStatusKey = new object();
Copy link
Member Author

Choose a reason for hiding this comment

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

Most of the noise in the diff here is just because I renamed the concept of NavigationStatus to CancellationStatus.

The code was never really interested in the concept of "did we navigate or not" - it was only interested in "should the circuit continue to exist", so this is a more precise name. It's relevant to change this now because there's now a second case where the circuit should not continue to exist (i.e., some component threw during prerendering, so we gave up on prerendering and released the DI scope immediately).

Copy link
Member

Choose a reason for hiding this comment

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

(i.e., some component threw during prerendering, so we gave up on prerendering and released the DI scope immediately).

I'm not sure what the E2E behavior is, but when multiple components get prerendered at the same time they share the same circuit, so isn't it bad to prevent other prerendered components from working? (limiting the error to the current prerendered component)

Copy link
Member Author

Choose a reason for hiding this comment

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

When a component throws an unhandled exception in prerendering, we return a 500 error to the browser, not a partially-complete HTML response.

Copy link
Member

Choose a reason for hiding this comment

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

I still have some doubts about this because people could write a try catch for these scenarios to keep other components in the page working and we are taking away that option, I'm not sure if that is something we want to consider.

(For example, don't dispose the circuit if some other component rendered successfully and only do the cleanup for the circuit on response started if we got a 500 out)

Copy link
Member Author

@SteveSandersonMS SteveSandersonMS Jul 4, 2019

Choose a reason for hiding this comment

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

That's a good question to raise, but it makes me think maybe we shouldn't be putting all prerendered components into the same circuit, or should give some other way to control how they are grouped into circuits so those groups can fail independently.

This is because in non-prerendering cases, we don't allow circuits/renderers/etc to continue to exist and be used once they have got into an undefined state through an unhandled exception during rendering or lifecycle methods. So in that sense it's good that we prevent it for prerendering too, and don't allow people to try/catch and then continue using that circuit state.

Copy link
Member

Choose a reason for hiding this comment

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

I think that's a fair answer, given that we are moving to a single circuit per connection model (independent of whether its prerendered or not)

I think that makes sense and leaves things in a more manageable state, so I'm ok with it.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should work hard to make life better when something is crashing. We should make sure that it fails hard, if users have multiple components on a page and they want to degrade gracefully they need to do it in their own code.

So I agree with the conclusion here.

{
// Avoid creating a circuit host if other component earlier in the pipeline already triggered
// a navigation request. Instead rendre nothing
// cancelation (e.g., by navigating or throwing). Instead render nothing.
Copy link
Member

Choose a reason for hiding this comment

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

nit, mixture of cancellation and cancelation

Copy link
Member Author

Choose a reason for hiding this comment

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

Good spot. I'll fix the comment typo in an unrelated PR just so I don't have to wait for CI checks here again.

@SteveSandersonMS SteveSandersonMS merged commit b31cd35 into master Jul 5, 2019
@SteveSandersonMS SteveSandersonMS deleted the stevesa/ensure-scope-disposal branch July 5, 2019 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Blazor doesn't always dispose the circuit's DI scope
3 participants