Reputation: 18031
I am studying MassTransit and ASP.NET Core, dependancy injection and successfully implemented something that works. I plan to use the Kestrel web server.
So I had to configure my ASP.NET core project this way in the Startup.cs
.
public void ConfigureServices(IServiceCollection services) {
...
var bus = Bus.Factory.CreateUsingRabbitMq(sbc => {
var host = sbc.Host(new Uri(address), h => {
h.Username("guest");
h.Password("guest");
});
});
services.AddSingleton<IBus>(bus);
services.AddScoped<IRequestClient<GetTagRequest, GetTagAnswer>>(x =>
new MessageRequestClient<GetTagRequest, GetTagAnswer>(x.GetRequiredService<IBus>(), new Uri(address + "/gettagrequest"), timeOut));
bus.Start(); // <= ok. how is the bus supposed to stop ?
...
Although this works fine, no tutorial mentioned anything about setting bus.Stop()
in an ASP.NET core project. I read in MassTransit documentation that a running bus could prevent a graceful exit.
bus.Stop()
in an ASP.NET Core project ?Upvotes: 6
Views: 4408
Reputation: 14034
To add to the existing answers:
MassTransit.AspNetCore
's IServiceCollection.AddMassTransit()
extension method, there's no need for a class level IBus
instance. Startup
's Configure()
supports DI, so you can do this instead:
public void Configure(IApplicationLifetime appLifetime, IBus bus)
{
appLifetime.ApplicationStarted.Register(() => bus.Start());
appLifetime.ApplicationStopping.Register(() => bus.Stop());
}
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 from 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();
Upvotes: 3
Reputation: 8539
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());
}
}
Upvotes: 9
Reputation: 101473
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.
Upvotes: 3