ISubscriptionStorage - rebus-org/Rebus GitHub Wiki

ISubscriptionStorage is Rebus' subscription storage abstraction that provides the ability for a publisher to persistently store subscriptions.

When a subscriber wants to subscribe to a specific event type, the subscriber will do a

await bus.Subscribe<SomethingInterestingHappened>();

which will make Rebus send a subscription request to the owner of the given event type. When the owner - who, in this case is a publisher - receives the request, the subscription must be saved somewhere. This is where the subscription storage comes in, basically just allowing a publisher to store a set of (eventType, subscriberInputQueueAddress) tuples.

When the publisher then publishes a SomethingInterestingHappened, the subscription storage will be used to look up a list of endpoints to whom the published message will be sent.

Current implementations

Out of the box, Rebus can store subscriptions in memory (thus not persistent in any way), and in a JSON file (which is not recommended for most scenarios). And then there's packages that allow you to store subscriptions in SQL Server, RavenDB, MongoDB, Postgres, etc.

Central subscription storages

The aforementioned subscription request can be bypassed when a subscription storage is centralized, which just means that both subscribers and publishers have access to the same central subscription storage.

This way, subscribers just register themselves directly in the shared subscription storage, where publishers will find them when they publish events.

A centralized subscription storage can be configured for database-based subscription storages with the isCentralized: true parameter on the configuration API.

The in-mem subscription storage, which is usually configured by going .Subscriptions(s => s.StoreInMemory()) in the Rebus configuration, can ALSO be configured to be centralized:

var subscriberStore = new InMemorySubscriberStore();

Configure.With(...)
    .(...)
    .Subscriptions(s => s.StoreInMemory(subscriberStore))
    .Start();

// configure more publishers/subscribers with the same
// subscriberStore...

Since subscriptions are residing in memory, it only makes sense to configure a centralized in-mem subscription storage when all endpoints sharing it are running in the same process/appdomain, e.g. when unit testing.

Certain transports and pub/sub messaging

A "subscription storage" is what allows Rebus to implement a proper publish/subscribe protocol on top of simple message queues and a database - but some transports have native support for pub/sub messaging, which Rebus can take advantage of.

Therefore, some transports (e.g. the Azure Service Bus transport and the RabbitMQ transport) will insert themselves as subscription storages, avoiding the need to introduce a shared database in order to have a "centralized subscription storage".