Background Work with Wolverine

Hey, did you know that JasperFx Software offers formal support plans for Marten and Wolverine? Not only are we making the “Critter Stack” tools be viable long term options for your shop, we’re also interested in hearing your opinions about the tools and how they should change. We’re also certainly open to help you succeed with your software development projects on a consulting basis whether you’re using any part of the Critter Stack or some completely different .NET server side tooling.

Drama came to the .NET community yet again in the past week or two when more folks noticed that Microsoft is planning to write some kind of “eventing framework” that may or may not end up competing with tools like Wolverine. By and large, that discussion seemed to be purposely designed to make my blood boil, but one comment caught my attention:

I have a fairly simple requirement where I want to fire an event and process that event in the background. A while back, I looked at many of the frameworks mentioned here, and they all seemed so convoluted. For the life of me, I could not figure out how to set up something as simple as this.

GitHub commenter

So challenge accepted! Starting with this post, I’m going to write another series of small posts to explore some of Wolverine’s rich capabilities for background processing much like the earlier Building a Critter Stack Application series.

Let’s start dirt simple and just build a little ASP.Net Core service that can use Wolverine to do some work in the background spawned by a call into an HTTP endpoint.

Let’s start by creating a new projection like so:

dotnet new webapi

Then add Wolverine — and just the core Wolverine for right now — with:

dotnet add package WolverineFx

For our simplistic service, let’s say that we have an HTTP endpoint that accepts a posted body like this type:

public record SignUpRequest(string Name, string Email);

and wants to send an email to that new user welcoming to our site. And we’d like to have that email sent in a background worker (in this case it’ll be published to a local, in memory queue and eventually run in a different thread from the original HTTP request).

Skipping ahead a little bit to the Wolverine usage, here’s a crude handler for our SignUpRequest using Wolverine:

public static class SendWelcomeEmailHandler
{
    public static void Handle(SignUpRequest @event, ILogger logger)
    {
        // Just logging, a real handler would obviously do something real
        // to send an email
        logger.LogInformation("Send a Send a welcome email to {Name} at {Email}", @event.Name, @event.Email);
    }
}

Now, let’s hook up Wolverine into our application with just one line of code in our Program file like so:

var builder = WebApplication.CreateBuilder(args);

// This is good enough for what we're trying to do
// at the moment
builder.Host.UseWolverine();

And finally, let’s build a little Minimal API endpoint in our system that will publish SignUpRequest as an “event” to be handled in the background by Wolverine like so:

app.MapPost("/signup", (SignUpRequest request, IMessageBus bus) 
    // IMessageBus is the primary entry point to Wolverine
    => bus.PublishAsync(request));

app.Run();

Alright, let’s fire up our app with F5, and run this endpoint from the Swashbuckle page:

And watching the console logging for our application, I see this log entry just proving that we did some background processing:

info: SignUpRequest[0]
      Send a Send a welcome email to Jeremy at jeremy@jasperfx.net

Woohoo, we’ve successfully utilized some background processing in our new ASP.Net Core system using Wolverine!

Alright, let’s talk about some details and facts I elided in the quick start:

  • Our message handler is found by Wolverine by looking for public classes suffixed with “Handler”, then public methods named “Handle”. The first argument is assumed to be the message type for that handler
  • When I called PublishAsync() up above, Wolverine is seeking to route that SignUpRequest as a message. In this simplistic case, Wolverine is defaulting to publishing the message to a local, in memory queue specifically for the SignUpRequest type
  • When that message is ultimately “received” by Wolverine, Wolverine is responsible for calling into our SignUpRequestHandler.Handle() method
  • There’s no farther wiring to do, Wolverine puts everything else together for us based on simple defaults

There’s of course, much, much more going on in terms of error handling, logging, possible parallelizing behind the scenes of even this simple example. There’s also certainly much more powerful abilities within Wolverine for much more advanced background processing that we’ll continue to explore later in this series.

Leave a comment