Skip to content

Basics

Wolverine Messaging Architecture

One way or another, Wolverine is all about messages within your system or between systems. Staying inside a single Wolverine system, a message is typically just a .NET class (or struct, but reserve that for strictly local usage) or C# record. A message generally represents either a "command" that should trigger an operation or an "event" that just lets another part of your system know that something happened. Here's a couple simple samples:

cs
// A "command" message
public record DebitAccount(long AccountId, decimal Amount);

// An "event" message
public record AccountOverdrawn(long AccountId);

snippet source | anchor

The next concept in Wolverine is a message handler, which is just a method that "knows" how to process an incoming message. Here's an extremely simple example:

cs
public static class DebitAccountHandler
{
    public static void Handle(DebitAccount account)
    {
        Console.WriteLine($"I'm supposed to debit {account.Amount} from account {account.AccountId}");
    }
}

snippet source | anchor

Wolverine can act as a completely local mediator tool that allows your code to invoke the handler for a message at any time without having to know anything about exactly how that message is processed with this usage:

cs
public async Task invoke_debit_account(IMessageBus bus)
{
    // Debit $250 from the account #2222
    await bus.InvokeAsync(new DebitAccount(2222, 250));
}

snippet source | anchor

There's certainly some value in Wolverine just being a command bus running inside of a single process, Wolverine also allows you to both publish and process messages received through external infrastructure like Rabbit MQ or Pulsar.

To put this into perspective, here's how a Wolverine application could be connected to the outside world:

Wolverine Messaging Architecture

TIP

The diagram above should just say "Message Handler" as Wolverine makes no structural differentiation between commands or events, but Jeremy is being too lazy to fix the diagram.

Terminology

  • Message -- Typically just a .NET class or C# record that can be easily serialized. See messages and serialization for more information
  • Envelope -- Wolverine's Envelope Wrapper model that wraps the raw messages with metadata
  • Message Handler -- A method or function that "knows" how to process an incoming message. See Message Handlers for more information
  • Transport -- This refers to the support within Wolverine for external messaging infrastructure tools like Rabbit MQ, Amazon SQS, Azure Service Bus, or Wolverine's built in TCP transport
  • Endpoint -- The configuration for a Wolverine connection to some sort of external resource like a Rabbit MQ exchange or an Amazon SQS queue. The Async API specification refers to this as a channel, and Wolverine may very well change its nomenclature in the future to be consistent with Async API.
  • Sending Agent -- You won't use this directly in your own code, but Wolverine's internal adapters to publish outgoing messages to transport endpoints
  • Listening Agent -- Again, an internal detail of Wolverine that receives messages from external transport endpoints, and mediates between the transports and executing the message handlers
  • Message Store -- Database storage for Wolverine's inbox/outbox persistent messaging
  • Durability Agent -- An internal subsystem in Wolverine that runs in a background service to interact with the message store for Wolverine's transactional inbox/outbox functionality

For more context, see

Released under the MIT License.