Skip to content

Customizable serverTimeoutInMilliseconds in Server-Side Blazor #18840

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

Closed
mvarblow opened this issue Feb 5, 2020 · 21 comments · Fixed by #46065
Closed

Customizable serverTimeoutInMilliseconds in Server-Side Blazor #18840

mvarblow opened this issue Feb 5, 2020 · 21 comments · Fixed by #46065
Assignees
Labels
affected-most This issue impacts most of the customers area-blazor Includes: Blazor, Razor Components area-signalr Includes: SignalR clients and servers Blazor ♥ SignalR This issue is related to the experience of Signal R and Blazor working together enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-blazor-server severity-blocking This label is used by an internal tool
Milestone

Comments

@mvarblow
Copy link

mvarblow commented Feb 5, 2020

When debugging a server-side blazor app we often see this error pop up in the client (browser) while stepping through code:

Error: Connection disconnected with error 'Error: Server timeout elapsed without receiving a message from the server.'.

This can be pretty disruptive, requiring a refresh of the browser to recover after continuing the debug session.

Presumably, this happens because the server isn't sending keepalives on the SignalR connection while I'm stepping through code in the debugger. When running in a 'development' environment, I'd like to be able to customize the serverTimeoutInMilliseconds on the HubConnection to prevent this. I see examples of how to customize the SignalR settings for a server-side Blazor app using code like this:

<environment exclude="Development">
    <script src="_framework/blazor.server.js"></script>
</environment>
<environment include="Development">
    <script src="_framework/blazor.server.js" autostart="false"></script>
    <script>
        (function start() {
            Blazor.start({
                logLevel: 1, // LogLevel.Debug
                configureSignalR: builder => builder.configureLogging("debug") // LogLevel.Debug
            });
        })();
    </script>
</environment>

However, I'm unable to change the serverTimeoutInMilliseconds setting. This setting is available on the HubConnection object, but I don't have access to that object. I only have access to HubConnectionBuilder. And HubConnectionBuilder doesn't have a serverTimeoutInMilliseconds property.

It seems like adding support for configuring the serverTimeoutInMilliseconds via HubConnectionBuilder would be the simplest solution.

Even nicer would be some way to configure this setting in my Startup.cs, probably with a new property available somewhere under the AddServerSideBlazor call, similar to how I can customize the server-side hub settings via AddServerSideBlazor().AddHubOptions(options => ... ).

@mkArtakMSFT mkArtakMSFT added the area-blazor Includes: Blazor, Razor Components label Feb 6, 2020
@javiercn
Copy link
Member

javiercn commented Feb 6, 2020

@mvarblow thanks for contacting us.

I believe there's already an issue open for this. @anurse is this something that can be done at the signalr level, even if its for all hubs, so that customers can get unblocked?

@analogrelay
Copy link
Contributor

When debugging a server-side blazor app we often see this error pop up in the client (browser) while stepping through code:

Yeah, debugging is a problematic thing for timeouts. We actually disable server-side timeouts when a debugger is attached but can’t control client-side timeouts in the same way.

@anurse is this something that can be done at the signalr level, even if its for all hubs, so that customers can get unblocked?

Right now it can only be set on the HubConnection in the client. Either Blazor will have to expose the HubConnection or SignalR will have to add support for setting the property in HubConnectionBuilder (or both). Seems like a reasonable ask, but it’s new API and not patchable. If someone wants to file a bug for the SignalR fix that would be great (on my phone at the moment).

In the short-term (since adding new APIs is a 5.0 change) is it possible to dig the HubConnection object out of Blazor somehow? Remember that “private” in TypeScript doesn’t mean anything :). It might also be possible to hack in a hook somehow. If it’s ONLY used in Development, it would be fairly reasonable to do something sneaky here ;).

Even nicer would be some way to configure this setting in my Startup.cs, probably with a new property available somewhere under the AddServerSideBlazor call, similar to how I can customize the server-side hub settings via AddServerSideBlazor().AddHubOptions(options => ... ).

We don’t support setting client options via server configuration by design. It was something that ASP.NET SignalR (for OWIN/System.Web apps) supported but it causes problems. This is the client’s timeout so it should be owned/set by the client.

@mkArtakMSFT mkArtakMSFT added this to the Next sprint planning milestone Feb 6, 2020
@mkArtakMSFT mkArtakMSFT added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Feb 6, 2020
@mvarblow
Copy link
Author

mvarblow commented Feb 6, 2020

Thanks, @anurse. I'd love to try something sneaky, but I haven't been able to come up with any way to get a hold of that HubConnection object. I don't see it getting stashed away anywhere. It seems to be referenced only as a method-scoped variable or parameter. And it doesn't seem to be passed to any functions I can hook into. As far as I can tell this internal implementation detail was successfully kept internal.

@mkArtakMSFT
Copy link
Member

We've moved this issue to the Backlog milestone. This means that it is not going to happen for the coming release. We will reassess the backlog following the current release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.

@javiercn javiercn added affected-most This issue impacts most of the customers severity-blocking This label is used by an internal tool labels Oct 9, 2020 — with ASP.NET Core Issue Ranking
@ghost
Copy link

ghost commented Oct 9, 2020

Thanks for contacting us.
We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We will evaluate the request when we are planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@ghost
Copy link

ghost commented Jul 20, 2021

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@alanma75
Copy link

hi, is there any update on this feature request?
in stress test our blazor server application is not sending the keepalive message in 30s and we see this server timeout error periodically.

@alanma75
Copy link

image
this is the log on ws traffic, during busy loading time, the down message gap was more than 30s, and client terminated the connection.

@JinShil
Copy link

JinShil commented Jul 13, 2022

Here's how I worked around this issue:

Blazor.start({
    configureSignalR: function (builder) {
        let c = builder.build();
        c.serverTimeoutInMilliseconds = 60000;
        c.keepAliveIntervalInMilliseconds = 30000;
        builder.build = () => {
            return c;
        };
    };
});

@The-Futurist
Copy link

The-Futurist commented Sep 2, 2022

Just FYI for everybody, the above code is placed inside _Layout.cshtml typically between the <environment include="Development"> tags.

@danroth27 danroth27 modified the milestones: Backlog, .NET 8 Planning Oct 13, 2022
@ghost
Copy link

ghost commented Oct 13, 2022

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@guardrex
Copy link
Contributor

guardrex commented Oct 24, 2022

This is resolved now. I understand the feedback.

I'm working on the doc updates to cover this. The workaround code shown above doesn't work, but setting the props on the hub connection in a component works for the client on both WASM and Server. The following approach for connection building is what what we show in the Blazor-SignalR tutorial. The following values are purely for demo purposes and aren't meant to make sense.

protected override async Task OnInitializedAsync()
{
    hubConnection = new HubConnectionBuilder()
        .WithUrl(Navigation.ToAbsoluteUri("/chathub"))
        .Build();

    hubConnection.ServerTimeout = TimeSpan.FromSeconds(61);
    hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(31);
    hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(17);

    Logger.LogInformation($"\n\n\nhubConnection.ServerTimeout: {hubConnection.ServerTimeout}" +
        $"\nhubConnection.HandshakeTimeout: {hubConnection.HandshakeTimeout}" +
        $"\nhubConnection.KeepAliveInterval: {hubConnection.KeepAliveInterval}\n\n");

    hubConnection.On<string, string>( ... );

    await hubConnection.StartAsync();
}

Output ...

hubConnection.ServerTimeout: 00:01:01
hubConnection.HandshakeTimeout: 00:00:31
hubConnection.KeepAliveInterval: 00:00:17

The code pitched earlier for Blazor.start is ineffective for both hosting models AFAICT. I'll angle coverage this way for Blazor Server and hosted WASM for the server (not shown here, but it will be on the PR) and client (shown above). If there's any further discussion on the doc updates, feel free to add remarks to the docs tracking issue at dotnet/AspNetCore.Docs#27320. I've placed a copy of this comment on the docs issue.

@javiercn
Copy link
Member

@guardrex I am not sure what you are trying to get at.

The snippet you described is for opening a hub within the app, not for configuring the Blazor Server hub.

For that, the only thing that works is:

Blazor.start({
    configureSignalR: function (builder) {
        let c = builder.build();
        c.serverTimeoutInMilliseconds = 60000;
        c.keepAliveIntervalInMilliseconds = 30000;
        builder.build = () => {
            return c;
        };
    };
});

@guardrex
Copy link
Contributor

guardrex commented Oct 24, 2022

This is resolved now. I understand the feedback.

Our tutorials show building a hub connection on the client in a component as I show above. Using the code that you just showed doesn't seem to have an effect on that hub connection for the server timeout or the keep-alive. Setting the properties directly on the hub connection do work.

I might be ... perhaps very likely now that you just said that ... misinterpreting what the difference is for setting the properties on the hub connection (after building a HubConnectionBuilder) in a component and setting the serverTimeoutInMilliseconds and keepAliveIntervalInMilliseconds in Blazor.start. That needs to be explained to me further.

Also, I haven't been able to figure out how to log that those settings for serverTimeoutInMilliseconds and keepAliveIntervalInMilliseconds have been set anywhere else in the app (e.g., in a component) via C#. I can perform trace logging on the hub connection built in the component, but the logging doesn't indicate anything about the values of serverTimeoutInMilliseconds and keepAliveIntervalInMilliseconds. I presume that they could be read via JS interop in a component tho, which is something that I didn't try.

@guardrex
Copy link
Contributor

guardrex commented Oct 24, 2022

This is resolved now. I understand the feedback.

I see you say ...

The snippet you described is for opening a hub within the app, not for configuring the Blazor Server hub.

Let me think about that a little more. Keep in mind that I'm not a SignalR guy really. What I know has come about via Blazor docs, not from using SignalR to any great degree outside of sample apps and working on our Blazor text. I never used it professionally prior to writing here.

@javiercn
Copy link
Member

@surayya-MS can you help bring clarity to the docs?

@guardrex
Copy link
Contributor

guardrex commented Oct 24, 2022

This is resolved now. I understand the feedback.

I'll just add one more bit on this.

not for configuring the Blazor Server hub.

Why isn't that performed in Program.cs as ...

builder.Services.AddServerSideBlazor()
    .AddHubOptions(options =>
    {
        options.ClientTimeoutInterval = TimeSpan.FromSeconds(60);
        options.HandshakeTimeout = TimeSpan.FromSeconds(30);
        options.KeepAliveInterval = TimeSpan.FromSeconds(15);
    });

... and besides that ... what about hosted WASM? We'd show this for the Server project ...

builder.Services.AddSignalR(options =>
{
    options.ClientTimeoutInterval = TimeSpan.FromSeconds(60);
    options.HandshakeTimeout = TimeSpan.FromSeconds(30);
    options.KeepAliveInterval = TimeSpan.FromSeconds(15);
});

... and then in the Client project in a "opening a hub within the app" (or a component of a Blazor Server app) ...

hubConnection.ServerTimeout = TimeSpan.FromSeconds(60);
hubConnection.HandshakeTimeout = TimeSpan.FromSeconds(30);
hubConnection.KeepAliveInterval = TimeSpan.FromSeconds(15);

Those server (Blazor Server, Program.cs) settings don't change the values of the hub connection on the client ("opening a hub within the app"). Those server (Blazor WASM, Program.cs) settings also don't change the values of the hub connection on the client in a hosted WASM app either. Setting them on the HubConnection in the components in both cases does work.

Ok ... I'll wait and move on to something else until we get the 🦖 straightened out 😄.

@javiercn
Copy link
Member

@guardrex that controls the timeouts on the server waiting on clients, the other controls the timeouts from the client waiting on the server.

@surayya-MS
Copy link
Member

n

It is not possible to set serverTimeoutInMilliseconds in Program.cs like so builder.Services.AddServerSideBlazor() .AddHubOptions(options => ..) . This is basically what the author of the issue asks us to implement. Either this or through Blazor.start({ configureSignalR: builder => ...})

The workaround works because it overrides the build method of the builder to return the hub connection with set serverTimeoutInMilliseconds.

Blazor.start({
    configureSignalR: function (builder) {
        let c = builder.build();
        c.serverTimeoutInMilliseconds = 60000;
        c.keepAliveIntervalInMilliseconds = 30000;
        builder.build = () => {
            return c;
        };
    };
});

@guardrex
Copy link
Contributor

guardrex commented Oct 24, 2022

Remarks removed and summarized (thank goodness! 🙈) on the docs PR at dotnet/AspNetCore.Docs#27374.

@javiercn
Copy link
Member

javiercn commented Oct 26, 2022

Tagging this as SignalR as we would like to be able to set these options in the builder directly rather than having to expose an extra knob.

@javiercn javiercn added area-blazor Includes: Blazor, Razor Components Blazor ♥ SignalR This issue is related to the experience of Signal R and Blazor working together feature-blazor-server area-signalr Includes: SignalR clients and servers and removed feature-blazor-server area-blazor Includes: Blazor, Razor Components labels Oct 26, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Feb 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affected-most This issue impacts most of the customers area-blazor Includes: Blazor, Razor Components area-signalr Includes: SignalR clients and servers Blazor ♥ SignalR This issue is related to the experience of Signal R and Blazor working together enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-blazor-server severity-blocking This label is used by an internal tool
Projects
None yet
10 participants