Skip to content

Different bus modes

mookid8000 edited this page Dec 27, 2012 · 15 revisions

Since Rebus can be configured in many ways, there's probably a few modes of operation that you should take into consideration when you determine your bus requirements.

One-way client mode

With MSMQ, you can run Rebus in the so-called one-way client mode. In this mode, the bus doesn't have its own input queue - therefore, it is capable only of sending messages.

This mode can be useful e.g. in systems where the web tier needs to send commands to application servers, but there's no need for the web tier to receive replies of any kind.

It follows from this that the bus cannot subscribe to anything either. It is allowed, however, to add a rebus-return-address header to a message and point to someone else, which will cause the recipient to reply to that someone.

An example configuration might look like this:

Configure.With(adapter)
    .Transport(t => t.UseMsmqInOneWayClientMode())
    (...)

Server

This is the simplest full-duplex mode of the bus. In this mode, the bus needs an input queue and therefore also an error queue.

The server's input queue address will be supplied as the rebus-return-address header in all sent messages, including the internally used subscription messages (which get sent when you bus.Subscribe).

For example:

Configure.With(adapter)
    .Transport(t => t.UseMsmqAndGetInputQueueNameFromAppConfig())
    (...)

In this case, we tell the configuration API to pick up the input queue name from the application's app.config. Therefore, you must also supply at least the following tiny bit of XML in your app.config:

<configSections>
    <section name="rebus" type="Rebus.Configuration.RebusConfigurationSection, Rebus" />
</configSections>

<rebus inputQueue="inputQueueName" errorQueue="errorQueueName" />

Publisher

The publisher mode covers the fact that the bus can handle the internally used subscription messages, and thus it can bus.Publish events as well.

A publisher should have some kind of persistent subscription storage (unless you're really really aware of what you're doing), otherwise subscribers might get dropped in the event of a publisher restart.

If you want to persist your subscriptions in a Microsoft SQL Server, you might want to configure the bus like this:

Configure.With(adapter)
    .Transport(t => t....)
    .Subscriptions(s => s.StoreInSqlServer(connectionString, subscriptionsTableName)
                         .EnsureTableIsCreated())
    (...)

where subscriptionsTableName points to a table in the database specified by the supplied ´connectionString` whose schema is this:

message_type nvarchar(200) not null
endpoint nvarchar(200) not null

and both columns make up the compound primary key. In the example above, EnsureTableIsCreated is called, invoking the automatic schema generation if the table is not present.

Process Manager

The process manager is a bus that can contain sagas. Sagas should most likely also be stored somewhere persistent, but it's entirely legal to choose the in-memory saga persister if your sagas are very short-lived and don't need to survive restarts.

If you want to configure Rebus to store saga data in Microsoft SQL Server, you can do it like this:

Configure.With(adapter)
    .Transport(t => t...)
    .Sagas(s => s.StoreInSqlServer(connectionString, sagaIndexTableName, sagaDataTableName)
                 .EnsureTablesAreCreated())
    (...)

where sagaIndexTableName is a table in the database specified by connectionString whose schema is like this:

saga_type nvarchar(40) not null
key nvarchar(200) not null
value nvarchar(200) not null
saga_id uniqueidentifier not null

and sagaDataTableName is a table whose schema is like this:

id uniqueidentifier not null
revision int not null
data nvarchar(max) not null

As you might have figured out already, Rebus requires two tables to be present in order to store sagas because it manually keeps an index of correlation properties persistent on the side.

In the example above EnsureTablesAreCreated is called, which will invoke the automatic schema generation if none of the specified table names are present in the database.

Clone this wiki locally