Particular / NServiceBus.Extensions.Hosting

NServiceBus extension to support Microsoft.Extensions.Hosting
Other
14 stars 14 forks source link

Subscribe to messages #40

Closed alhardy closed 4 years ago

alhardy commented 4 years ago

What is the recommended way to subscribe to messages in an ASP.NET Core application?

kbaley commented 4 years ago

Hi @alhardy

We have a couple of samples for ASP.NET Core applications depending on whether you have a web application or a web API application:

https://docs.particular.net/samples/web/asp-web-application/ https://docs.particular.net/samples/web/send-from-aspnetcore-webapi/

alhardy commented 4 years ago

Thanks @kbaley. I can't see any message subscription on the endpoint in those examples.

Where is the best place to resolve the endpoint using the hosting package and subscribe to message when not using auto subscribe.

If I resolve a scoped instance on startup, the endpoint hasn't been started yet via the hosted service.

dvdstelt commented 4 years ago

Hi @alhardy,

Subscriptions work the same in every case. NServiceBus can figure this out automatically with most transports and you don't have to do anything. If you do need to subscribe, this is the way to do it, using RegisterPublisher: https://docs.particular.net/nservicebus/messaging/routing#event-routing-message-driven

With manual subscriptions, this is the way to register for an event: https://docs.particular.net/nservicebus/messaging/publish-subscribe/controlling-what-is-subscribed#manually-subscribing-to-a-message

If I resolve a scoped instance on startup, the endpoint hasn't been started yet via the hosted service.

Not sure what you mean with this? Maybe you're refering to the racing condition in ASP.NET Core 2.x or earlier? This explains how hosting in ASP.NET Core is done with a remark about earlier versions of .NET Core: https://docs.particular.net/samples/web/send-from-aspnetcore-webapi/

timbussmann commented 4 years ago

@alhardy if you need to call Subscribe manually when the endpoint starts, I'd use a FeatureStartupTask for now.

It requires a little bit of boilerplate code though, I think that might be something to improve for future versions. Any thoughts on a specific API proposal which would be the most useful to you? e.g. something like UseEndpoint(c => { ...}, session => session.Subscribe(..))?

timbussmann commented 4 years ago

sorry, I forgot to attach a link to the FeatureStartupTask doco: https://docs.particular.net/nservicebus/pipeline/features#feature-startup-tasks

mauroservienti commented 4 years ago

@alhardy in case you still looking for a solution I packaged @timbussmann suggestion into a Nuget package, the code is available at https://github.com/mauroservienti/NServiceBus.Extensions.EndpointStarted and the package is on Nuget https://www.nuget.org/packages/NServiceBus.Extensions.EndpointStarted/

andreasohlund commented 4 years ago

@alhardy In the upcoming 1.1.0 release we've made some improvements to the way the message session is provided that would allow you to call subscribe/unsubscribe in the start/stop method of your own hosted service. As long as you configure your own hosted service after the call to UseNServiceBus (order of configuration is currently the only way MS provides to control startup order) you can do the following:

Host.CreateDefaultBuilder()
.UseNServiceBus(hostBuilderContext =>
{
    var endpointConfiguration = new EndpointConfiguration("MyEndpoint");
    ....
    return endpointConfiguration;
})
.ConfigureServices((ctx, serviceProvider) => 
    serviceProvider.AddHostedService<MySubscriptionManager>())
...

class MySubscriptionManager: IHostedService
{
    public HostedServiceThatAccessSessionInStart(IMessageSession messageSession)
    {
        this.messageSession = messageSession;
    }
    public Task StartAsync(CancellationToken cancellationToken)
    {
        return messageSession.Subscribe<MyEvent>();
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return messageSession.Unsubscribe<MyEvent>();
    }

    readonly IMessageSession messageSession;
}

Here is a test that shows this in action.

I'll close this issue for now but please get in touch again if none of the prosed solutions works out for you.