Stream "/event-stream?channels=CHANNELNAME" not working

Javascript Client, “/event-stream?channels=CHANNELNAME” not working on netcore3.0 console app. Same code on netcore2.2 console app works fine.

Is there anything I can do?

Kind regards

Please provide as much details about the error you can when reporting an issue.

What JavaScript Client are you referring to and what exactly is not working? Are any HTTP Requests failing? If they please provide the raw HTTP Request/Responses Headers.

Sorry for lack of details, here is a bit broader explanation.

Environment: dotnet core 3.0 preview 9
ServiceStack: 5.6.1
Sharpscript

In apphost serverevents plugin is registered.

When app is buit with netcoreapp2.2 as target framework everything works fine.
However when target framework is set to 3.0, following occurs:

  • eventstream request repeats
  • there is no data in response
  • no heartbeat

Page that is consuming event-stream:

<!--
title:Dashboard
-->

{{ 'requires-role-support' | partial }}

{{ sendToGateway("DashboardRequest") | assignTo: data }}

...PARTIALS...

{{#raw appendTo scripts}}
<script>
lib = window["@servicestack/client"];
for (var k in lib) { window[k] = lib[k] }

client = new ServerEventsClient('/', ["dashboard"], {
    receivers: {
        elem: {
            disconnected: function (id) {
                //$('#'+id) set warning
            },
            connected: function(id) {
                //$('#'+id) set ok
            },
            set: function(input) {
                //$('#'+id) set value
            }
        }
    }
}).start();
</script>
{{/raw}}

More details can be seen here:

Kind regards

It’s because they’ve disabled sync writes which SSE uses, you can enable it by configuring the Host Server that you’re using, e.g:

public void ConfigureServices(IServiceCollection services)
{
    // If using Kestrel:
    services.Configure<KestrelServerOptions>(options =>
    {
        options.AllowSynchronousIO = true;
    });

    // If using IIS:
    services.Configure<IISServerOptions>(options =>
    {
        options.AllowSynchronousIO = true;
    });
}

Thanks.
Following the link you provided there is this excerpt from link further https://github.com/aspnet/AspNetCore/issues/7644 :

AllowSynchronousIO is a option in each server that enables or disables sync IO APIs like HttpReqeuest.Body.Read, HttpResponse.Body.Write, Stream.Flush, etc… These APIs have long been a source of thread starvation and application hangs.

Current app is suffering from this exactly plus memory leak (which does not occur when serverevents are disabled). Due to nature of application, currently we can live without this part (live system status dashboard) since we can extract data from other means, or with manual webpage refresh.

Is there a plan from your side to rework server events to async IO in perspective?

Kind regards

The existing implementation can’t be refactored as it would break every existing Notification API which are all synchronous, I’ll look at adding async alternatives for each sync API.

I’ve just added new Async APIs which will let you avoid any sync writes in the latest v5.6.1 that’s now available on MyGet.

Here are the new Async APIs, they’re all copies of existing Sync APIs with an *Async suffix and an optional CancellationToken, i.e:

public interface IServerEvents {

Task NotifyAllAsync(string sel, object msg, CancellationToken ct)
Task NotifyChannelAsync(string chan, string sel, object msg, CancellationToken ct)
Task NotifySubscriptionAsync(string subId, string sel, object msg, string chan, CancellationToken ct)
Task NotifyUserIdAsync(string userId, string sel, object msg, string chan, CancellationToken ct)
Task NotifyUserNameAsync(string userName, string sel, object msg, string chan, CancellationToken ct)
Task NotifySessionAsync(string sessionId, string sel, object msg, string chan, CancellationToken ct)

}

If you’ve got any server event handlers registered, you can switch them over to use new Async APIs as well:

public class ServerEventsFeature : IPlugin {

Func<IEventSubscription, Task> OnSubscribeAsync
Func<IEventSubscription,Task> OnUnsubscribeAsync
Func<IEventSubscription, IResponse, string, Task> OnPublishAsync

}