Skip to main content
Version: 2.4.1

Wolverine

Overview​

RCommon.Wolverine integrates WolverineFx as a distributed event handler for the RCommon event handling pipeline. It is focused on event production and subscription rather than the request-response mediator pattern.

The package provides:

  • WolverineEventHandlingBuilder / IWolverineEventHandlingBuilder — registers Wolverine-based subscribers through the RCommon fluent builder.
  • PublishWithWolverineEventProducer — publishes events to all Wolverine handlers using IMessageBus.PublishAsync (fan-out).
  • SendWithWolverineEventProducer — sends events to a single Wolverine handler using IMessageBus.SendAsync (point-to-point).
  • WolverineEventHandler<TEvent> — bridges Wolverine's message dispatch to RCommon's ISubscriber<TEvent> abstraction.

Events must implement ISerializableEvent (from RCommon.Models) to flow through the Wolverine producers.

Installation​

NuGet Package
dotnet add package RCommon.Wolverine

This package depends on RCommon.Core and WolverineFx. Wolverine itself requires host-level setup via UseWolverine() on the application host builder — see the Wolverine documentation for transport and endpoint configuration.

Configuration​

Wolverine is configured at the host level and within the RCommon builder. Register the Wolverine host extension on the application host builder, then wire up RCommon subscribers.

using RCommon;
using RCommon.Wolverine;
using Wolverine;

var builder = WebApplication.CreateBuilder(args);

// Configure Wolverine at the host level
builder.Host.UseWolverine(opts =>
{
// Configure transports, endpoints, and discovery here
opts.Discovery.IncludeAssembly(typeof(Program).Assembly);
});

// Configure RCommon with Wolverine event handling
builder.Services.AddRCommon()
.WithEventHandling<WolverineEventHandlingBuilder>(wolverine =>
{
wolverine.AddSubscriber<OrderPlacedEvent, OrderPlacedEventHandler>();
wolverine.AddSubscriber<OrderShippedEvent, OrderShippedEventHandler>();
});

Usage​

Defining an event​

Events dispatched through Wolverine must implement ISerializableEvent:

using RCommon.Models.Events;

public class OrderPlacedEvent : ISerializableEvent
{
public OrderPlacedEvent(Guid orderId, Guid customerId, DateTime placedAt)
{
OrderId = orderId;
CustomerId = customerId;
PlacedAt = placedAt;
}

public Guid OrderId { get; }
public Guid CustomerId { get; }
public DateTime PlacedAt { get; }
}

Creating a subscriber​

Implement ISubscriber<TEvent> from RCommon.EventHandling.Subscribers. This is the same interface used by MediatR subscribers — the Wolverine adapter bridges message dispatch to it automatically through WolverineEventHandler<TEvent>.

using RCommon.EventHandling.Subscribers;

public class OrderPlacedEventHandler : ISubscriber<OrderPlacedEvent>
{
private readonly IEmailService _emailService;

public OrderPlacedEventHandler(IEmailService emailService)
{
_emailService = emailService;
}

public async Task HandleAsync(OrderPlacedEvent @event, CancellationToken cancellationToken = default)
{
await _emailService.SendOrderConfirmationAsync(@event.CustomerId, @event.OrderId, cancellationToken);
}
}

Registration​

Register subscribers using the IWolverineEventHandlingBuilder extension method. Each call records the event-to-producer subscription in the EventSubscriptionManager so the router only delivers the event to the producers registered for it.

builder.Services.AddRCommon()
.WithEventHandling<WolverineEventHandlingBuilder>(wolverine =>
{
wolverine.AddSubscriber<OrderPlacedEvent, OrderPlacedEventHandler>();
});

If you need to construct the subscriber with a factory delegate:

wolverine.AddSubscriber<OrderPlacedEvent, OrderPlacedEventHandler>(
sp => new OrderPlacedEventHandler(sp.GetRequiredService<IEmailService>()));

Producing events​

Use PublishWithWolverineEventProducer for fan-out delivery (all subscribers receive the event) or SendWithWolverineEventProducer for point-to-point delivery (one handler). Register the appropriate producer when setting up your event bus:

using RCommon.EventHandling.Producers;
using RCommon.Wolverine.Producers;

// Fan-out: all subscribed handlers receive the event
builder.Services.AddScoped<IEventProducer, PublishWithWolverineEventProducer>();

// Point-to-point: only one handler receives the event
builder.Services.AddScoped<IEventProducer, SendWithWolverineEventProducer>();

Produce events through RCommon's IEventBus or by raising domain events that flow through the event router — the producers are invoked by the routing infrastructure automatically.

API Summary​

IWolverineEventHandlingBuilder extension methods​

MethodDescription
AddSubscriber<TEvent, TEventHandler>()Registers TEventHandler as a scoped ISubscriber<TEvent> and records the subscription in the EventSubscriptionManager.
AddSubscriber<TEvent, TEventHandler>(Func<IServiceProvider, TEventHandler>)Same as above, but uses a factory delegate to construct the subscriber.

PublishWithWolverineEventProducer​

MemberDescription
ProduceEventAsync<T>(T, CancellationToken)Calls IMessageBus.PublishAsync<T> to deliver the event to all Wolverine handlers subscribed to T. Skips delivery if the event type is not subscribed to this producer.

SendWithWolverineEventProducer​

MemberDescription
ProduceEventAsync<T>(T, CancellationToken)Calls IMessageBus.SendAsync<T> to deliver the event to a single Wolverine handler. Skips delivery if the event type is not subscribed to this producer.

WolverineEventHandler<TEvent>​

MemberDescription
HandleAsync(TEvent, CancellationToken)Called by Wolverine's message dispatch infrastructure. Delegates to the injected ISubscriber<TEvent>.

Key interfaces and base types​

TypePackageDescription
IWolverineEventHandlingBuilderRCommon.WolverineBuilder interface for configuring Wolverine event handling. Extends IEventHandlingBuilder.
WolverineEventHandlingBuilderRCommon.WolverineDefault implementation. Constructed by WithEventHandling<WolverineEventHandlingBuilder>.
ISerializableEventRCommon.ModelsMarker interface required on all events dispatched through Wolverine producers.
ISubscriber<TEvent>RCommon.EventHandlingApplication-level handler interface. Implement this for your event handling logic.
IWolverineEventHandler<TEvent>RCommon.WolverineWolverine-facing handler interface implemented by WolverineEventHandler<TEvent>.
RCommonRCommon