Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Redis claim check

This sample shows how to implement the Claim Check pattern with Redis as a data store.

Prerequisites

This sample connects to a local Redis instance. See the Redis guidance for installing a new instance.

Alternatively with Docker installed locally, execute the following command in the solution directory:

docker compose up -d

Overview

graph LR Sender --"1. Write data"--> Redis Sender --"2. Send message"--> Receiver Receiver --"3. Retrieve data"-->Redis
  1. The Sender endpoint generates data and stores it in the Redis instance
  2. The Sender endpoint sends a message with the Redis key to the Receiver endpoint
  3. The Receiver endpoint retrieves the data from the Redis instance using the key in the message

Running the project

  1. Run a Redis instance.
  2. Run the Sender endpoint to generate data and send a message to the Receiver endpoint.
  3. Run the Receiver endpoint to process the message.

Code walkthrough

The solution contains a claim check implementation that writes to and reads from Redis.

public class RedisClaimCheck(string configuration) : IClaimCheck
{
    private IConnectionMultiplexer redis;

    public async Task<Stream> Get(
        string key,
        CancellationToken cancellationToken = default)
    {
        var db = redis.GetDatabase();
        byte[] redisValue = await db.StringGetAsync(key);
        return new MemoryStream(redisValue);
    }

    public async Task<string> Put(
        Stream stream,
        TimeSpan timeToBeReceived,
        CancellationToken cancellationToken = default)
    {
        var db = redis.GetDatabase();
        var key = $"particular:sample:claimcheck:{Guid.NewGuid()}";
        var value = ((MemoryStream)stream).ToArray();
        await db.StringSetAsync(
            key,
            value,
            timeToBeReceived == TimeSpan.MaxValue ? null : timeToBeReceived
        );
        return key;
    }

    public async Task Start(CancellationToken cancellationToken = default)
    {
        redis = await ConnectionMultiplexer.ConnectAsync(configuration);
    }
}

Each endpoint is configured to use the Redis claim check. The conventions are updated to configure NServiceBus to understand which properties should have the claim check applied.

endpointConfig.UseClaimCheck(
    _ => new RedisClaimCheck("localhost"),
    new SystemJsonClaimCheckSerializer()
);
endpointConfig.Conventions()
    .DefiningClaimCheckPropertiesAs(
        prop => prop.Name.StartsWith("Large")
    );

When the Sender endpoint starts, a random string is generated and assigned to the property LargeText on the message. NServiceBus transparently stores the data in Redis and sends the message without this large property.

await messageSession.Send(new ProcessText
{
    LargeText = GetRandomText(1 * Megabyte)
}, cancellationToken: stoppingToken);

On the receiving side, NServiceBus loads the data from Redis before the message handler is called. When the handler is invoked, the LargeText property is populated with the data from Redis.

public Task Handle(ProcessText message, IMessageHandlerContext context)
{
    log.LogInformation(
        "Most common letter in sample: {mostCommonLetter}",
        MostCommonLetter(message.LargeText)
    );

    return Task.CompletedTask;
}

If you have other scenarios in which you use Redis, or are missing specific capabilities, share them and help shape the future of the platform.

Related Articles