Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Outbox with NHibernate Persistence

NuGet Package: NServiceBus.NHibernate (8.x - 8.3)
Target Version: NServiceBus 7.x

The outbox feature requires persistent storage in order to store the messages and enable deduplication.

Table

To keep track of duplicate messages, the NHibernate implementation of the outbox requires the creation of an OutboxRecord table.

Customizing outbox record persistence

By default the outbox records are persisted in the following way:

  • The table has an auto-incremented integer primary key.
  • The MessageId column has a unique index.
  • There are indices on Dispatched and DispatchedAt columns.

The following API can be used to provide a different mapping of outbox data to the underlying storage:

var persistence = endpointConfiguration.UsePersistence<NHibernatePersistence>();
persistence.UseOutboxRecord<MyOutboxRecord, MyOutboxRecordMapping>();
public class MyOutboxRecord :
    IOutboxRecord
{
    public virtual string MessageId { get; set; }
    public virtual bool Dispatched { get; set; }
    public virtual DateTime? DispatchedAt { get; set; }
    public virtual string TransportOperations { get; set; }
}

public class MyOutboxRecordMapping :
    ClassMapping<MyOutboxRecord>
{
    public MyOutboxRecordMapping()
    {
        Table("MyOutboxTable");
        Id(
            idProperty: record => record.MessageId,
            idMapper: mapper => mapper.Generator(Generators.Assigned));
        Property(
            property: record => record.Dispatched,
            mapping: mapper =>
            {
                mapper.Column(c => c.NotNullable(true));
                mapper.Index("OutboxRecord_Dispatched_Idx");
            });
        Property(
            property: record => record.DispatchedAt,
            mapping: pm => pm.Index("OutboxRecord_DispatchedAt_Idx"));
        Property(
            property: record => record.TransportOperations,
            mapping: mapper => mapper.Type(NHibernateUtil.StringClob));
    }
}

If custom mapping is required, the following characteristics of the original mapping must be preserved:

  • Values stored in the MessageId column must be unique and an attempt to insert a duplicate entry must cause an exception.
  • Querying by Dispatched and DispatchedAt columns must be efficient because these columns are used by the cleanup process to remove outdated records.

Deduplication record lifespan

By default, the NHibernate implementation keeps deduplication records for seven days and checks for purgeable records every minute.

Specify different values in the config file using timestamp strings:

<appSettings>
  <add key="NServiceBus/Outbox/NHibernate/TimeToKeepDeduplicationData"
       value="7.00:00:00" />
  <add key="NServiceBus/Outbox/NHibernate/FrequencyToRunDeduplicationDataCleanup"
       value="00:01:00" />
</appSettings>

By specifying a value of -00:00:00.001 (i.e. 1 millisecond, the value of Timeout.InfiniteTimeSpan) for the NServiceBus/Outbox/NHibernate/FrequencyToRunDeduplicationDataCleanup app settings, the cleanup task is disabled. This is useful when an endpoint is scaled out and instances are competing to run the cleanup task.

Related Articles

  • Outbox
    Reliable messaging without distributed transactions.