Published on

implementing redis pub/sub with .net aspire: a simple guide

Authors

what is redis pub/sub?

redis pub/sub (publish/subscribe) is a messaging pattern where:

  • publishers send messages to channels
  • subscribers listen to specific channels
  • publishers and subscribers are decoupled
  • messages are delivered in real-time

first, let's look at the apphost configuration:

App Host:

var builder = DistributedApplication.CreateBuilder(args);

var redis = builder.AddRedis("redis");

builder.AddProject<Projects.Api>("api")
    .WithReference(redis)
    .WithReplicas(1);

builder.AddProject<Projects.Worker>("worker")
    .WithReference(redis);

await builder.Build().RunAsync();

in this configuration, we set up redis. you need to install Aspire.Hosting.Redis package.

the application consists of an api service for publishing messages and a background worker for reading them. the api service sends the message to redis channel:

Api/Program.cs

// ... (initialization code)
builder.AddRedisDistributedCache("redis");

as you can see we need to add redis to api service first. for this you need to install Aspire.StackExchange.Redis.DistributedCaching package.

app.MapPost("/send-message", async ([FromBody] SendMessageRequest request, IConnectionMultiplexer connectionMultiplexer) =>
{
    await connectionMultiplexer.GetSubscriber().PublishAsync(Constants.DefaultChannel, request.Message);
    return Results.Ok();
});

the background worker then gets the messages from redis channel and writes a log message:

using RedisPubSub.ServiceDefaults;
using StackExchange.Redis;

namespace Worker;

public class Worker(ILogger<Worker> logger, IConnectionMultiplexer connectionMultiplexer) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            await connectionMultiplexer.GetSubscriber().SubscribeAsync(Constants.DefaultChannel, (channel, message) =>
            {
                logger.LogWarning("Here is the message: {Message} from channel: {ChannelName}", message, Constants.DefaultChannel);
            });

            await Task.Delay(5000, stoppingToken);
        }
    }
}

here are screenshots from testing:

api-send
api-telemetry
worker-telemetry
worker-log

conclusion

with .net aspire, implementing redis pub/sub becomes straightforward. this pattern is excellent for building scalable, real-time applications with decoupled components. as you explore further, you'll find even more ways to leverage redis and .net aspire in your cloud-native applications.

for the complete source code of this example, you can visit: https://github.com/eminvergil/aspire-samples