aspnet / SignalR

[Archived] Incredibly simple real-time web for ASP.NET Core. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
2.38k stars 448 forks source link

Hubs run as background processes #2574

Closed granthoff1107 closed 5 years ago

granthoff1107 commented 6 years ago

.Net core provides new functionality to allow microservices to be run through background processes/ When Clients send updates through websocket or through rest they maybe required to transmit to 1000s of clients at the same time. I would perfer if the completion of my request wasn't dependent on this.

Signalr should use IHostedService, implementations to allow pushing to clients to run in the background

public interface IHostedService
{
    //
    // Summary:
    //     Triggered when the application host is ready to start the service.
    Task StartAsync(CancellationToken cancellationToken);
    //
    // Summary:
    //     Triggered when the application host is performing a graceful shutdown.
    Task StopAsync(CancellationToken cancellationToken);
}

More information can be found here: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.1

davidfowl commented 6 years ago

Nothing special has to be done here. You can do something like this today https://github.com/davidfowl/UT3/blob/fb12e182d42d2a5a902c1979ea0e91b66fe60607/UTT/Scavenger.cs#L35.

https://github.com/davidfowl/UT3/blob/fb12e182d42d2a5a902c1979ea0e91b66fe60607/UTT/Startup.cs#L46

granthoff1107 commented 6 years ago

Thanks for the sample, I just found out about HostedServices today, they’re so useful.

granthoff1107 commented 6 years ago

I switched over to use the QueuedHostedService, So I can queue tasks to be sent out on my hubs.

public class QueuedHostedService : BackgroundService
{
    private Task _backgroundTask;
    private readonly ILogger _logger;

    public IBackgroundTaskQueue TaskQueue { get; }

    public QueuedHostedService(IBackgroundTaskQueue taskQueue, ILoggerFactory loggerFactory)
    {
        TaskQueue = taskQueue;
        _logger = loggerFactory.CreateLogger<QueuedHostedService>();
    }

    protected async override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (false == stoppingToken.IsCancellationRequested)
        {
            var workItem = await TaskQueue.DequeueAsync(stoppingToken);
            try
            {
                await workItem(stoppingToken);
            }
            catch (Exception ex)
            {
                this._logger.LogError(ex, $"Error occurred executing {nameof(workItem)}.");
            }
        }
    }
}

Currently I'm using a multi-hub architecture, so I have a hub per service. In your example you explicitly pass the hub to the background service like so:

https://github.com/davidfowl/UT3/blob/fb12e182d42d2a5a902c1979ea0e91b66fe60607/UTT/Scavenger.cs#L13

However since I'm using a Generic Hub, I won't know the Hub context type head of time. Hosted Services need to obtain their own copy of their dependencies, I'm not sure what's the best way to go about obtaining the IHubContext<ServiceHub>, should I just pass in a Func to grab it from the scope factory?

davidfowl commented 6 years ago

We should really update that example to show how it would work with services. Are you queueing different types of background work? If yes then you need to pass the IHubContext explicitly.

granthoff1107 commented 6 years ago

@davidfowl, I thought it wasn’t safe to pass things obtained from the web requests dependency injector to the background service?

Or is it okay to pass the hubcontext since it’s a singleton?

For now I’ve, used the service locator anti-pattern by modifing the task queue to give you access to the service provider.

But I’d love a better way to do it

aspnet-hello commented 5 years ago

We periodically close 'discussion' issues that have not been updated in a long period of time.

We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate.