Rebus.ServiceProvider 10.0.0-alpha04

This is a prerelease version of Rebus.ServiceProvider.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Rebus.ServiceProvider --version 10.0.0-alpha04                
NuGet\Install-Package Rebus.ServiceProvider -Version 10.0.0-alpha04                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Rebus.ServiceProvider" Version="10.0.0-alpha04" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Rebus.ServiceProvider --version 10.0.0-alpha04                
#r "nuget: Rebus.ServiceProvider, 10.0.0-alpha04"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Rebus.ServiceProvider as a Cake Addin
#addin nuget:?package=Rebus.ServiceProvider&version=10.0.0-alpha04&prerelease

// Install Rebus.ServiceProvider as a Cake Tool
#tool nuget:?package=Rebus.ServiceProvider&version=10.0.0-alpha04&prerelease                

Rebus.ServiceProvider

install from nuget

Provides an Microsoft.Extensions.DependencyInjection-based container adapter for Rebus.

alternate text is missing from this package README image


Intro

This container adapter is meant to be used with the generic host introduced with .NET Core 2.1, which has evolved into the ubiquitous hosting model for .NET.

Quickstart

When you configure your services, do this to invoke the Rebus configuration spell:

services.AddRebus(
    configure => configure
        .Transport(t => t.UseAzureServiceBus(connectionString, queueName))
);

and that is all there is to it! ๐Ÿ˜ Rebus will use an IHostedService behind the covers to manage the Rebus instance, so it'll be started and stopped as the host conducts its background services.

If you need access to something that must be resolved from the container (e.g. configurations and stuff), there's an overload that passes the service provider to the configurer:

services.AddRebus(
    (configure, provider) => {
        var asb = provider.GetRequiredService<IOptions<AsbSettings>>();
        var connectionString = asb.ConnectionString;
        var queueName = asb.InputQueueName;
        
        return configure
            .Transport(t => t.UseAzureServiceBus(connectionString, queueName));
    }
);

If you want to subscribe to stuff at startup, use the onCreated callback:

services.AddRebus(
    (configure, provider) => {
        var asb = provider.GetRequiredService<IOptions<AsbSettings>>();
        var connectionString = asb.ConnectionString;
        var queueName = asb.InputQueueName;
        
        return configure
            .Transport(t => t.UseAzureServiceBus(connectionString, queueName));
    },

    onCreated: async bus => {
        await bus.Subscribe<FirstEvent>();
        await bus.Subscribe<SecondEvent>();
    }
);

and that's basically it.

If you're interested in hosting multiple Rebus instances inside a single process, please read on. ๐Ÿ™‚

Logging

โ„น๏ธ Please note that logging will be automatically configured - if possible, and if you haven't configured anything yourself.

As logging is integrated with the host, Rebus will simply direct all of its logging to loggers created using the ILoggerFactory provided by the host, so if you want to log by some other means (e.g. with Serilog), you can simply use the appropriate Serilog integration package and direct the host's logs to a Serilog sink.

It's still possible to e.g. append the usual .Logging(l => l.Serilog()) if you want to do that, but it's often easier to just let Rebus use the host logging mechanism, and then configure logging in the host like you would anyway.

Hosting outside of the generic host

It can still be used outside of the generic host, but that will require usage to follow a pattern like this:

var services = new ServiceCollection();

services.AddRebus(...);

using var provider = services.BuildServiceProvider();

// THIS ๐Ÿ‘‡ will start the bus(es)  
provider.StartRebus();

Hosting inside the generic host

โš  With the generic host (which is what you're using, if you've created a console app, a background worker, or a web app), the configuration extensions in this package rely on IHostedService and how the host uses these, and therefore the above call to StartRebus() shoule NOT be made.

โ„น With the generic host, there's two major modes of operation:

  1. Starting one or more Rebus instances, using the host's container instance
  2. Starting one or more Rebus instances, using one or more separate container instances

Usage

Starting one or more Rebus instances, using the host's container instance

When sharing the host's container instance, starting one or more Rebus instances is as easy as

services.AddRebus(...);

as many times as you like.

โš  But please note that there can be only ONE PRIMARY Rebus instance so you'll most likely follow a pattern like this:

// This one ๐Ÿ‘‡ will be the primary bus instance
services.AddRebus(...);

services.AddRebus(isPrimaryBus: false, ...);

services.AddRebus(isPrimaryBus: false, ...);

if you want to add multiple Rebus instances.

When you add a Rebus instance with AddRebus, you can configure it the way you're used to via its RebusConfigurer and its extensions, so it could be something like

services.AddRebus(
    configure => configure
        .Transport(t => t.UseAzureServiceBus(connectionString, "my-queue-name"))
        .Serializer(s => s.UseSystemTextJson())
);

for a single bus instance (which is also the default), or something like

services.AddRebus(
    configure => configure
        .Transport(t => t.UseAzureServiceBus(connectionString, "some-kind-of-processor"))
        .Serializer(s => s.UseSystemTextJson())
);

services.AddRebus(
    isPrimaryBus: false,

    configure: configure => configure
        .Transport(t => t.UseAzureServiceBus(connectionString, "some-kind-of-background-processor"))
        .Serializer(s => s.UseSystemTextJson())
);

to add two bus instances. If you want to subscribe to something when starting up, there's an optional onCreated parameter that makes this possible, e.g. like this:

services.AddRebus(
    configure => configure
        .Transport(t => t.UseAzureServiceBus(connectionString, "my-queue-name"))
        .Serializer(s => s.UseSystemTextJson()),

    onCreated: async bus => {
        await bus.Subscribe<SomethingInterestingHappened>();
        await bus.Subscribe<AnotherInterestingThingHappened>();
    }
);

The callback passed as onCreated will be executed when the bus is created and operational, but before it has begun consuming messages.

Starting one or more Rebus instances, using one or more separate container instances

When you want to host additional Rebus instances in the same process, but you want an extra degree of separation from your host application (e.g. if you're following the "modular monolith" approach), you can call the AddRebusService on the host builder for each independent background service you would like to add.

Since the background services are separate from the host, they each have their own container instance, and so you'll need to register whatever stuff they need to work.

In your startup code, you'll most likely find something that goes like this:

var builder = WebApplication.CreateBuilder(args);

// register stuff in builder.Services here

var app = builder.Build();

// maybe configure web app middlewares here

await app.RunAsync();

This builder has a Host property, which is where you will find the AddRebusService extension method:

builder.Host.AddRebusService(
    services => (...)
);

It has a single callback, which is where you can configure the necessary services for the container instance dedicated to this background service. It requires that at least ONE call be made to AddRebus like this:

builder.Host.AddRebusService(
    services => services.AddRebus(...)
);

but otherwise it works like your normal service collection. This also means that it's totally fine to add multiple Rebus instance to it as well, if you like (but you'll probably want to mostly stay away from that to avoid giving your team mates a headache ๐Ÿคฏ).

A typical configuraion could look like this (assuming that you're into the aesthetics of wrapping your registrations behind IServiceCollection extensions):

builder.Host.AddRebusService(
    services => {
        services.AddMyEfDatabaseContext();

        services.AddMyRepositories();
        
        services.AddMyApplicationServices();

        services.AddRebus(
            configure => configure
                .Transport(t => t.UseAzureServiceBus(connectionString, "my-queue-name"))
        );

        services.AddRebusHandler<SomeMessageHandler>();
        services.AddRebusHandler<AnotherMessageHandler>();
    }
);

โ„น When using the separate background service approach described here, the container will forward calls for

  • Microsoft.Extensions.Hosting.IHostApplicationLifetime
  • Microsoft.Extensions.Logging.ILoggerFactory

to the host's container, which essentially makes these things transparently available, as singletons, to the separate Rebus service.

If you forward requests for other singletons to the host's container you can add to the list of forwarded singleton types:

builder.Host.AddRebusService(
    services => services.AddRebus(...),
    typeof(IMyDateTimeProvider),
    typeof(IMyImportantService),
    ... etc
);

Primary bus instance?

When adding multiple bus instances to a single container instance, there's one big question that needs to be answered: Which bus instance will be returned if you resolve IBus from it?

var bus = serviceProvider.GetRequiredService<IBus>();

// ???

or if you have an IBus injected:

public class SomethingPublisher
{
    public SomethingPublisher(IBus bus) => ... //< ???
}

This where the concept of "default bus" is relevant.

Specific bus instances

If you need to be able to later resolve a specific bus instance from the service provider, you can register a bus with a key:

services.AddRebus(
    configure => configure
        .Transport(t => t.UseAzureServiceBus(connectionString, queueName)),
    
    key: "my-favorite-bus"
);

Later, when your app is running, you will then be able to retrieve that specific bus instance via IBusRegistry like so:

var registry = provider.GetRequiredService<IBusRegistry>(); //< or have this injected

var bus = registry.GetBus("my-favorite-bus");

// voilรก! ๐ŸŽ‰

Delayed start of the bus

When you configure the bus, e.g. with

services.AddRebus(
    configure => configure
        .Transport(t => t.UseAzureServiceBus(connectionString, queueName)),

    key: "my-favorite-bus"
);

and then the host starts up (or you call the StartRebus() extension method on the service provider), the bus will automatically be started (i.e. it will start consuming messages).

You can delay the time of when message consumption is begun by setting startAutomatically: false in the call to AddRebus:

services.AddRebus(
    configure => configure
        .Transport(t => t.UseAzureServiceBus(connectionString, queueName)),

    key: "my-favorite-bus",
    startAutomatically: false //< the bus will be "started" with 0 workers, i.e. it will not consume anything
);

At a later time, when you think it's about time the bus gets to taste some sweet message goodness, you can start it via the registry:

var registry = provider.GetRequiredService<IBusRegistry>(); //< or have this injected

registry.StartBus("my-favorite-bus");

// voilรก! ๐ŸŽ‰

Since starting the bus this way requires that you retrieve it via the bus registry, it's a hard requirement that a KEY is provided when calling AddRebus.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (31)

Showing the top 5 NuGet packages that depend on Rebus.ServiceProvider:

Package Downloads
Elsa.Core

Elsa is a set of workflow libraries and tools that enable lean and mean workflowing capabilities in any .NET Core application. This package contains the core of Elsa. Tip: reference the `Elsa` package instead of this one.

Umbraco.Deploy.Cloud

Umbraco Deploy Cloud provides reliable deployment of schema, functionality, structure and content between Umbraco Cloud environments. This package can be used with Umbraco CMS version 9 and higher, for version 8 or below, please contact Umbraco support.

EasyDesk.CleanArchitecture.Infrastructure

Utilities for the infrastructure layer of the clean architecture as seen by EasyDesk.

Volo.Abp.EventBus.Rebus

Package Description

Rebus.ServiceProvider.Named

Provides named bus instance support for Rebus, enabling hosting of multiple instances.

GitHub repositories (5)

Showing the top 5 popular GitHub repositories that depend on Rebus.ServiceProvider:

Repository Stars
abpframework/abp
Open-source web application framework for ASP.NET Core! Offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET. Provides the fundamental infrastructure, cross-cutting-concern implementations, startup templates, application modules, UI themes, tooling and documentation.
CodeMazeBlog/CodeMazeGuides
The main repository for all the Code Maze guides
mastreeno/Merp
An event based Micro ERP
jxnkwlp/abp-elsa-module
Elsa abp module and workflow app
rebus-org/RebusSamples
Small sample projects
Version Downloads Last updated
10.3.0 34,326 11/14/2024
10.2.0 105,116 9/9/2024
10.1.2 770,091 3/15/2024
10.1.1 45,162 2/24/2024
10.1.0 72,295 1/30/2024
10.0.0 448,837 11/15/2023
10.0.0-alpha04 4,303 6/24/2023
10.0.0-alpha03 1,497 6/14/2023
10.0.0-alpha02 1,261 6/14/2023
10.0.0-alpha01 5,175 3/27/2023
9.1.0 195,013 7/30/2023
9.0.0 294,761 3/27/2023
9.0.0-b02 2,530 3/15/2023
9.0.0-b01 1,283 3/15/2023
8.4.0 1,530,488 11/9/2022
8.3.1 302,699 9/14/2022
8.3.0 123,668 9/2/2022
8.2.0 10,391 8/25/2022
8.1.0 31,930 8/1/2022
8.0.0 35,446 7/5/2022
8.0.0-b06 22,506 4/19/2022
8.0.0-b05 1,339 4/4/2022
8.0.0-b04 21,646 2/9/2022
8.0.0-b03 4,319 1/21/2022
8.0.0-b02 1,282 1/19/2022
8.0.0-b01 1,284 1/17/2022
7.0.0 2,557,029 11/12/2021
7.0.0-b3 1,643 11/9/2021
7.0.0-b2 4,075 6/29/2021
7.0.0-b1 1,431 6/29/2021
6.4.1 936,653 2/23/2021
6.4.0 5,590 2/21/2021
6.3.1 193,067 1/29/2021
6.3.0 1,823 1/28/2021
6.2.0 28,571 1/21/2021
6.1.0 1,873 1/21/2021
6.0.0 179,997 12/3/2020
6.0.0-a3 213 1/21/2021
6.0.0-a2 396 11/4/2020
6.0.0-a1 2,062 8/31/2020
5.0.6 555,002 3/31/2020
5.0.5 116,507 3/24/2020
5.0.4 3,455 3/23/2020
5.0.3 3,808 3/17/2020
5.0.2 55,541 2/22/2020
5.0.1 3,008 2/18/2020
5.0.0 6,022 2/11/2020
5.0.0-b08 2,805 1/17/2020
5.0.0-b07 1,668 1/16/2020
5.0.0-b06 20,757 12/9/2019
5.0.0-b05 1,599 12/9/2019
5.0.0-b04 4,634 11/4/2019
5.0.0-b03 5,161 9/24/2019
5.0.0-b02 1,590 9/24/2019
5.0.0-b01 26,297 2/1/2019
4.0.2 526,020 11/26/2018
4.0.1 348,103 10/31/2017
4.0.0 6,034 8/16/2017
4.0.0-b07 2,116 8/11/2017
4.0.0-b06 2,143 7/31/2017
4.0.0-b05 2,284 6/22/2017
4.0.0-b04 2,421 5/18/2017
4.0.0-b02 2,160 5/17/2017
4.0.0-b01 2,112 4/30/2017
3.0.0 159,336 1/5/2017
2.0.0 3,478 9/20/2016
2.0.0-b01 2,021 9/9/2016
0.99.74 3,444 8/29/2016