How to stop a MassTransit bus in an ASP.NET Core server?
You can use ApplicationLifetime
events. Just make your IBus
object class level variable.
public class Startup
{
private IBus _bus;
public void ConfigureServices(IServiceCollection services) {
/* ... */
_bus = Bus.Factory.CreateUsingRabbitMq ...
/* ... */
}
public void Configure(IApplicationLifetime appLifetime)
{
appLifetime.ApplicationStarted.Register(() => _bus.Start());
appLifetime.ApplicationStopping.Register(() => _bus.Stop());
}
}
There is IApplicationLifetime
in .NET Core, which has several CancellationToken
properties, including ApplicationStopped
. So when you need to do something after asp.net application is shutdown and all requests are processed (like stopping your bus) - you can do it like this:
// lifetime will be injected to Configure from DI container
public void Configure(IApplicationBuilder app, IApplicationLifetime lifetime) {
// subscribe to ApplicationStopped
lifetime.ApplicationStopped.Register(OnApplicationStopped);
// the rest
}
private void OnApplicationStopped() {
_bus.Stop();
}
It's always good to explicitly release resources even on process shutdown. For example, some message might still be in transition when the process will be killed after shutdown. Doing explicit dispose will allow this transition to complete.
To add to the existing answers:
- If you use the
MassTransit.AspNetCore
'sIServiceCollection.AddMassTransit()
extension method, there's no need for a class levelIBus
instance.Startup
'sConfigure()
supports DI, so you can do this instead:
If you don't want to use the package, you can still register IBus with the DI container (like in the question) and request it frompublic void Configure(IApplicationLifetime appLifetime, IBus bus) { appLifetime.ApplicationStarted.Register(() => bus.Start()); appLifetime.ApplicationStopping.Register(() => bus.Stop()); }
Configure()
. The ASP.NET Core DI sample uses an IHostedService instead:
public class BusService : IHostedService { private readonly IBusControl _busControl; public BusService(IBusControl busControl) { _busControl = busControl; } public Task StartAsync(CancellationToken cancellationToken) => _busControl.StartAsync(cancellationToken); public Task StopAsync(CancellationToken cancellationToken) => _busControl.StopAsync(cancellationToken); }
The service is registered as:
services.AddSingleton<IHostedService, BusService>();
For more information on
IHostedService
, here's the doc page. I'm not sure I like the idea of having a background service just to stop the bus. Anyway, the sample repo I picked this example from is worth referring to.The third option is to do it yourself in
Main()
. Something like:var host = CreateWebHostBuilder(args).Build(); var bus = host.Services.GetRequiredService<IBusControl>(); await bus.StartAsync(); await host.RunAsync(); await bus.StopAsync();