Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

MongoDB Persistence

NuGet Package: NServiceBus.Storage.MongoDB (4.x)
Target Version: NServiceBus 9.x

Uses the MongoDB document database for storage.

Persistence at a glance

For a description of each feature, see the persistence at a glance legend.

Feature
Supported storage typesSagas, Outbox, Subscriptions
TransactionsEnabled and required by default
Concurrency controlPessimistic concurrency only
Scripted deploymentNot supported
InstallersNone. Documents are created in database at runtime as needed.

Usage

Add a NuGet package reference to NServiceBus.Storage.MongoDB. Configure the endpoint to use the persistence through the following configuration API:

endpointConfiguration.UsePersistence<MongoPersistence>();

Customizing the connection

By default, a MongoClient is created that connects to mongodb://localhost:27017 and uses the endpoint name as its database name.

Customize the server, port, and authentication database using the following configuration API:

var persistence = endpointConfiguration.UsePersistence<MongoPersistence>();
persistence.MongoClient(new MongoClient("SharedMongoUrl"));

Specify the database to use for NServiceBus documents using the following configuration API:

var persistence = endpointConfiguration.UsePersistence<MongoPersistence>();
persistence.DatabaseName("DatabaseName");

Transactions

MongoDB transactions are enabled and required by default. This allows the persister to use pessimistic locking and to update multiple saga instances and commit them atomically during message processing.

Disabling transactions

The following configuration API is available for compatibility with MongoDB server configurations which don't support transactions:

var persistence = endpointConfiguration.UsePersistence<MongoPersistence>();
persistence.UseTransactions(false);

Note that this disables the ability to use pessimistic locking for sagas which might result in higher contention in the database.

Shared transactions

NServiceBus supports sharing MongoDB sessions between Saga persistence, Outbox storage, and business data. The shared session can be used to persist multiple document updates atomically.

To use the shared transaction in a message handler:

public Task Handle(MyMessage message, IMessageHandlerContext context)
{
    var session = context.SynchronizedStorageSession.GetClientSession();
    var collection = session.Client.GetDatabase("mydatabase").GetCollection<MyBusinessObject>("mycollection");
    return collection.InsertOneAsync(session, new MyBusinessObject(), null, context.CancellationToken);
}

The shared session can also be accessed via dependency injection using the IMongoSynchronizedStorageSession interface:

class MyService
{
    IMongoSynchronizedStorageSession sharedSession;

    // Resolved from DI container
    public MyService(IMongoSynchronizedStorageSession sharedSession)
    {
        this.sharedSession = sharedSession;
    }

    public Task Create()
    {
        return sharedSession.MongoSession.Client
            .GetDatabase("mydatabase")
            .GetCollection<MyBusinessObject>("mycollection")
            .InsertOneAsync(sharedSession.MongoSession, new MyBusinessObject());
    }
}

Testing

The TestableMongoSynchronizedStorageSession class in the NServiceBus.Testing namespace has been provided to facilitate testing a handler that utilizes the shared transaction feature.

Outbox cleanup

When the outbox is enabled, the deduplication data is kept for seven days by default. To customize this time frame, use the following API:

var persistence = endpointConfiguration.UsePersistence<MongoPersistence>();
persistence.TimeToKeepOutboxDeduplicationData(TimeSpan.FromDays(30));

Saga concurrency

When simultaneously handling messages, conflicts may occur. See below for examples of the exceptions which are thrown. Saga concurrency explains how these conflicts are handled, and contains guidance for high-load scenarios.

Starting a saga

Example exception:

MongoDB.Driver.MongoCommandException: Command insert failed: WriteConflict.

Updating or deleting saga data

Starting from version 2.2, MongoDB persistence uses exclusive locks when updating or deleting saga data. The saga persister tries to acquire an exclusive lock on the saga data for up to 60 seconds. If, within this time period, an exclusive lock cannot be acquired, a TimeoutException is thrown and regular message retry policies are applied.

Example exception:

System.TimeoutException: Unable to acquire exclusive write lock for saga on collection 'collectionName'

In versions prior to version 2.2, MongoDB persistence uses optimistic concurrency control when updating or deleting saga data.

Example exception:

MongoDB.Driver.MongoCommandException: Command update failed: WriteConflict.

Samples

Related Articles