Skip to content

Redis

Not published by ForkForward Cargo yet

This page refers to a package that ForkForward Cargo does not publish yet: MassTransit.Redis. The code is in the repository, but the package name is not decided. Don't add the original MassTransit package instead: a project must not reference ForkForward Cargo and MassTransit packages at the same time, as both contain MassTransit.dll. See Packages.

Redis is a very popular key-value store, which is known for being very fast. To support Redis, MassTransit uses the StackExchange.Redis library.

Warning

Redis only supports event correlation by CorrelationId, it does not support queries. If a saga uses expression-based correlation, a NotImplementedByDesignException will be thrown.

Info

The Redis package also supports the recent fork of Redis called Valkey

Storing a saga in Redis requires an additional interface, ISagaVersion, which has a Version property used for optimistic concurrency. An example saga is shown below.

public class OrderState :
    SagaStateMachineInstance,
    ISagaVersion
{
    public Guid CorrelationId { get; set; }
    public string CurrentState { get; set; }

    public DateTime? OrderDate { get; set; }

    public int Version { get; set; }
}

Configuration

To configure Redis as the saga repository for a saga, use the code shown below using the AddMassTransit container extension. This will configure Redis to connect to the local Redis instance on the default port using Optimistic concurrency. This will also store the ConnectionMultiplexer in the container as a single instance, which will be disposed by the container.

services.AddMassTransit(x =>
{
    const string configurationString = "127.0.0.1";

    x.AddSagaStateMachine<OrderStateMachine, OrderState>()
        .RedisRepository(configurationString);
});

The example below includes all the configuration options, in cases where additional settings are required.

services.AddMassTransit(x =>
{
    const string configurationString = "127.0.0.1";

    x.AddSagaStateMachine<OrderStateMachine, OrderState>()
        .RedisRepository(r =>
        {
            r.DatabaseConfiguration(configurationString);

            // Default is Optimistic
            r.ConcurrencyMode = ConcurrencyMode.Pessimistic;

            // Optional, prefix each saga instance key with the string specified
            // resulting dev:c6cfd285-80b2-4c12-bcd3-56a00d994736
            r.KeyPrefix = "dev";

            // Optional, to customize the lock key
            r.LockSuffix = "-lockage";

            // Optional, the default is 30 seconds
            r.LockTimeout = TimeSpan.FromSeconds(90);
        });;
});

Concurrency

Redis supports both Optimistic (default) and Pessimistic concurrency.

In optimistic mode, the saga instance is not locked before reading, which can ultimately lead to a write conflict if the instance was updated by another message. The Version property is used to compare that the update would not overwrite a previous update. It is recommended that a retry policy is configured (using UseMessageRetry, see the exceptions documentation).

Pessimistic concurrency uses the Redis lock mechanism. During the message processing, the repository will lock the saga instance before reading it, so that any concurrent attempts to lock the same instance will wait until the current message has completed or the lock timeout expires.