RavenDB Persistence

Project Hosting
NuGet Package NServiceBus.RavenDB (5.x)
Target NServiceBus Version: 7.x
RavenDB's implementation of distributed transactions contains a bug that could cause an endpoint, in certain (rare) conditions, to lose data. If RavenDB is configured to enlist in distributed transactions, read DTC not supported for RavenDB Persistence.

Uses the RavenDB document database for storage.

RavenDB versions

Specific versions of RavenDB Persistence are tied to a major version of NServiceBus and also designed to work with a specific version of the RavenDB client library. When releasing a new major version of NServiceBus, the corresponding RavenDB Persistence release will use the last supported version of RavenDB, so that it is never necessary to upgrade both NServiceBus and RavenDB at the same time.

NServiceBusRavenDB PersistenceRavenDB ClientPlatform
7.xNot Yet Released4.0.NET 4.6+ / .NET Core 2.0
7.x5.0.x3.5.NET 4.5.2 / .NET Core 2.0
6.x4.2.x3.5.NET 4.5.2
6.x4.0.x3.0.NET 4.5.2
5.x3.2.x3.5.NET 4.5.2
5.x3.0.x3.0.NET 4.5.2
5.x2.x2.5.NET 4.5.2

See the NServiceBus Packages Supported Versions to see the support details for each version of RavenDB Persistence.

Connection options for RavenDB

There are a variety of options for configuring the connection to a RavenDB Server. See RavenDB Connection Options for more details.

Supported clustering configurations

NServiceBus does not support multi-master RavenDB cluster configurations. Only fail-over clustering modes are supported. Consistency cannot be guaranteerd in multi-master configurations. NServiceBus cannot do automated conflict resolution for conflicts in multi-master configurations.

Shared session

NServiceBus supports sharing the same RavenDB document session between Saga persistence, Outbox persistence, and business data, so that a single persistence transaction can be used to persist the data for all three concerns atomically. Shared sessions are automatically configured when an endpoint has enabled the Outbox feature or contains sagas.

To use the shared session in a message handler:

public class HandlerThatUsesSession :
    IHandleMessages<MyMessage>
{
    public Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        var document = new MyDocument();
        var ravenSession = context.SynchronizedStorageSession.RavenSession();
        return ravenSession.StoreAsync(document);
    }
}

Although additional database operations inside a saga handler are not recommended (see warning below) the shared session can also be accessed from a saga handler:

Other than interacting with its own internal state, a saga should not access a database, call out to web services, or access other resources. See Accessing databases and other resources from a saga.

If the situation is special enough to warrant going against this recommendation, the following documentation will describe how to do so.

public class SagaThatUsesSession :
    Saga<SagaThatUsesSession.SagaData>,
    IHandleMessages<MyMessage>
{
    public Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        var document = new MyDocument();
        var ravenSession = context.SynchronizedStorageSession.RavenSession();
        return ravenSession.StoreAsync(document);
    }

Customizing the IDocumentSession

The creation of the RavenDB IDocumentSession instance used by NServiceBus and made available as the shared session can be customized as shown in the following snippet. Despite the name of the method, this option does not enable the shared session but only affects the customization of that session.

var documentStore = new DocumentStore();
// configure documentStore here
var persistence = endpointConfiguration.UsePersistence<RavenDBPersistence>();
persistence.UseSharedAsyncSession(
    getAsyncSessionFunc: headers =>
    {
        var session = documentStore.OpenAsyncSession();
        // customize session here
        return session;
    });
When the RavenDB DocumentStore is created by the user at endpoint configuration time it's important to dispose it, by calling the Dispose() method, before shutting down the endpoint process.

The getAsyncSessionFunc function receives the incoming message headers as an argument. Message headers can be used to support multi-tenant environments customizing the shared session based on the currently processed message.

Distributed Transaction Coordinator settings

The RavenDB client requires a unique Guid to identify it to the Distributed Transaction Coordinator, and a method of storing DTC transaction recovery information in the case of process faults. By default, NServiceBus uses IsolatedStorageTransactionRecoveryStorage as its transaction recovery storage. Under certain high-load situations, this has been known to result in a TransactionAbortedException or IsolatedStorageException.

In order to set DTC settings that are safe for production use, refer to Setting RavenDB DTC settings manually.

Subscription persister and message versioning

The behavior of the RavenDB subscription persistence differs from other NServiceBus persisters in the way it handles versioning of message assemblies. It's important to understand this difference, especially when using a deployment solution that automatically increments assembly version numbers with each build.

To learn about message versioning as it relates to the RavenDB subscription persister, refer to RavenDB subscription versioning.

Viewing the data

Open a web browser and type the URL of the RavenDB server. This opens the RavenDB Studio.

Samples

Related Articles


Last modified