Topics
Wolverine supports publishing to Rabbit MQ topic exchanges with this usage:
using var host = await Host.CreateDefaultBuilder()
.UseWolverine(opts =>
{
opts.UseRabbitMq();
opts.Publish(x =>
{
x.MessagesFromNamespace("SomeNamespace");
x.ToRabbitTopics("topics-exchange", ex =>
{
// optionally configure the exchange
});
});
opts.ListenToRabbitQueue("");
}).StartAsync();
While we're specifying the exchange name ("topics-exchange"), we did nothing to specify the topic name. With this set up, when you publish a message in this application like so:
var publisher = host.MessageBus();
await publisher.SendAsync(new Message1());
You will be sending that message to the "topics-exchange" with a topic name derived from the message type. By default that topic name will be Wolverine's message type alias. Unless explicitly overridden, that alias is the full type name of the message type.
That topic name derivation can be overridden explicitly by placing the [Topic]
attribute on a message type like so:
[Topic("color.blue")]
public class FirstMessage
{
public Guid Id { get; set; } = Guid.NewGuid();
}
Of course, you can always explicitly send a message to a specific topic with this syntax:
await publisher.BroadcastToTopicAsync("color.*", new Message1());
Note two things about the code above:
- The
IMessageBus.BroadcastToTopicAsync()
method will fail if there is not the declared topic exchange endpoint that we configured above - You can use Rabbit MQ topic matching patterns in addition to using the exact topic
Lastly, to set up listening to specific topic names or topic patterns, you just need to declare bindings between a topic name or pattern, the topics exchange, and the queues you're listening to in your application. Lot of words, here's some code from the Wolverine test suite:
theSender = Host.CreateDefaultBuilder()
.UseWolverine(opts =>
{
opts.UseRabbitMq("host=localhost;port=5672").AutoProvision();
opts.PublishAllMessages().ToRabbitTopics("wolverine.topics", exchange =>
{
exchange.BindTopic("color.green").ToQueue("green");
exchange.BindTopic("color.blue").ToQueue("blue");
exchange.BindTopic("color.*").ToQueue("all");
});
opts.PublishMessagesToRabbitMqExchange<RoutedMessage>("wolverine.topics", m => m.TopicName);
}).Start();
Publishing by Topic Rule
As of Wolverine 1.16, you can specify publishing rules for messages by supplying the logic to determine the topic name from the message itself. Let's say that we have an interface that several of our message types implement like so:
public interface ITenantMessage
{
string TenantId { get; }
}
Let's say that any message that implements that interface, we want published to the topic for that messages TenantId
. We can implement that rule like so:
var builder = Host.CreateApplicationBuilder();
builder.UseWolverine(opts =>
{
opts.UseRabbitMq();
// Publish any message that implements ITenantMessage to
// a Rabbit MQ "Topic" exchange named "tenant.messages"
opts.PublishMessagesToRabbitMqExchange<ITenantMessage>("tenant.messages",
m => $"{m.GetType().Name.ToLower()}/{m.TenantId}")
// Specify or configure sending through Wolverine for all
// messages through this Exchange
.BufferedInMemory();
});
using var host = builder.Build();
await host.StartAsync();