feat(redis): named-broker and broker-per-tenant support (GH-3309)#3321
Merged
Conversation
Bring the Redis Streams transport up to parity with RabbitMQ / NATS on the two established multi-broker features. Named broker: - Add protocol-carrying constructors for each connection source; endpoint URIs and scheme checks now use the instance Protocol instead of the hard-coded "redis" literal, so a named broker's endpoints use the broker name as their URI scheme and never collide with the default redis:// broker. - AddNamedRedisBroker (connection string / ConfigurationOptions / IConnectionMultiplexer / factory overloads) constructs a distinct RedisTransport keyed by Protocol; ListenToRedisStreamOnNamedBroker / ToRedisStreamOnNamedBroker pin endpoints to it. Broker-per-tenant: - New RedisTenant (dedicated, lazily-built IConnectionMultiplexer per tenant); RedisTransport.Tenants + GetTenantConnection; eager connect/ping in ConnectAsync; disposal of Wolverine-built tenant multiplexers only. - AddTenant + ConfigureMultiTenancy on the expression. - CreateSender fans out to a TenantedSender of inline senders (never a BatchedSender under TenantedSender — GH-2361); BuildListenerAsync builds a CompoundListener with one listener per dedicated-connection tenant wrapped in ReceiverWithRules + TenantIdRule. Sender/listener take an optional tenant multiplexer and target their own database on it; tenant listeners provision their consumer group on their own server. Tests: RedisNamedBrokerTests (registration + two-container send/round-trip) and RedisPerTenantConnectionTests (tenant vs default server + inbound tenant stamp), using a shared second-Redis-server class fixture and raw XREAD to prove the exact target server. Docs: named-broker + multi-tenancy sections in redis.md. Full Wolverine.Redis.Tests green (131); wolverine.slnx Release clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jeremydmiller
marked this pull request as ready for review
July 6, 2026 11:01
This was referenced Jul 9, 2026
Merged
This was referenced Jul 14, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3309
Brings the Redis Streams transport (
Wolverine.Redis) up to parity with RabbitMQ / NATS on the two established multi-broker features. It had neither before.Feature 1 — Named broker
RedisTransportnow stores an instanceProtocol(heaviest part of this change): protocol-carrying constructors for every connection source, and all endpoint-URI construction + scheme checks (buildStreamCache,ResourceUri,findEndpointByUri,tryBuildSystemEndpoints,RedisHealthCheck) use it instead of the hard-coded"redis"literal. A named broker's endpoints therefore carry the broker name as their URI scheme (secondary://stream/0/orders) and never collide with the defaultredis://broker.AddNamedRedisBroker(BrokerName, …)with connection-string /ConfigurationOptions/IConnectionMultiplexer/ factory overloads. Because Redis needs connection info, it constructsnew RedisTransport(name.Name, …)andTransports.Add(...)directly rather than relying onGetOrCreate's reflective ctor.ListenToRedisStreamOnNamedBroker/ToRedisStreamOnNamedBrokerpin endpoints to a named broker (throws a helpful error if the broker wasn't registered first).Feature 2 — Broker-per-tenant (modeled after NATS)
RedisTenant— a dedicated, lazily-builtIConnectionMultiplexerper tenant (connection string /ConfigurationOptions/ caller-managed multiplexer).RedisTransport.Tenants+GetTenantConnection; eager connect+ping inConnectAsync; disposal inDisposeAsyncof only the multiplexers Wolverine built itself.AddTenant(tenantId, …)+ConfigureMultiTenancy(TenantedIdBehavior)on the expression.CreateSenderfans out to a frameworkTenantedSender, routed byEnvelope.TenantId;BuildListenerAsyncbuilds aCompoundListenerwith one listener per dedicated-connection tenant wrapped inReceiverWithRules+TenantIdRule. The sender/listener take an optional tenant multiplexer and target their own database on it. Tenant listeners provision their consumer group on their own server.GH-2361
Both the tenant senders and the default fallback under
TenantedSenderare the fire-and-forgetInlineRedisStreamSender— notBatchedSender+RedisSenderProtocol.TenantedSenderdoesn't forwardRegisterCallback, so a callback-requiring sender under it would silently drop every message. Verified by the inbound tenant round-trip test (a silent drop would surface as a timeout).Tests
RedisNamedBrokerRegistrationTests(no broker; always runs in CI) — distinct transport per broker, endpoints use the broker name as scheme, unregistered-broker throws.RedisNamedBrokerTests+RedisPerTenantConnectionTests— spin up a second Redis container (server B) via a sharedIClassFixture; rawXREADproves a…OnNamedBroker/TenantId-tagged message lands on server B (and a default on server A), plus an inbound round-trip stamped with the broker scheme / tenant id.Wolverine.Redis.Testsgreen (131 passed).dotnet build wolverine.slnx -c Releaseclean (0 warnings, 0 errors).Docs
Added "Connecting to Multiple Brokers" and "Multi-Tenancy" sections to
docs/guide/messaging/transports/redis.mdwith compilingsnippetsamples; reverted unrelated mdsnippets churn.Caveats
🤖 Generated with Claude Code