Tag Archives: Jasper

Introducing BlueMilk: StructureMap’s Replacement & Jasper’s Special Sauce

BlueMilk is the codename for a new project that’s an outgrowth from our new Jasper framework. Specifically, BlueMilk is extracting the runtime code generation and compilation “Special Sauce” support code that’s in Jasper now into a stand alone library. Building upon the runtime code generation, the logical next step was to make BlueMilk into the intended successor to the venerable StructureMap project as a fast, minimal IoC container on its own, but also supports inlining the service activation code into Jasper’s message and HTTP request handlers.

I think these are the key points for BlueMilk:

  1. Support the essential functionality and configuration API of StructureMap to be an offramp for folks invested in StructureMap that want to move to a faster option in their Netstandard2 applications
  2. Align much closer with the ASP.Net team’s DI compliance behavior. In some cases like object lifecycles, this is a breaking change with StructureMap’s traditional behavior and I don’t entirely agree with their choices, but .Net is their world and all us scrappy community OSS authors are just living in it.
  3. Easy integration into ASP.Net Core applications by directly supporting their abstractions (IServiceCollection, IServiceProvider, ServiceDescriptor, IServiceScope, etc.) out of the box.
  4. Trade in some of the runtime flexibility that StructureMap had in favor of better performance (and fewer ways for users to get themselves in a tangle)
  5. Expose the runtime code generation and compilation model (originally built for Marten, but we took it out later) in a separate library because a few folks have expressed some interest in having just that without using Jasper

There’s a preliminary Nuget up this morning (0.1.0) that supports some of StructureMap’s behavior and all of the ASP.Net Core compliance. You can use a container like this:

// Idiomatic StructureMap
var container = new Container(_ =>
{
    _.For<IWidget>().Use<AWidget>().Named("A");
    
    // StructureMap's old type scanning
    _.Scan(s =>
    {
        s.TheCallingAssembly();
        s.WithDefaultConventions();
    });
});

var widget = container.GetInstance<IWidget>();

// ASP.Net Core DI compatible
IServiceProvider container2 = new Container(_ =>
{
    _.AddTransient<IWidget, AWidget>();
    _.AddSingleton(new MoneyWidget());
});

var widget2 = container.GetService<IWidget>();

 

My Thoughts on Project Scope

I only started working on BlueMilk by itself over the holidays, so it’s not like anything is truly set in concrete, but this list is what I think the scope would be. My philosophy here is to jettison many of the features in StructureMap that cause internal complexity, performance issues, or generate loads of user questions and edge case bugs.

Core Functionality

  1. All ASP.Net Core DI compliance — lifecycle management (note that it’s different than StructureMap’s lifecycle definitions), object disposal, basic service resolution, open generic support, dealing with enumerable types
  2. StructureMap’s basic support for service location
  3. Nested Containers (scoped container)
  4. Type Scanning from StructureMap
  5. Service resolution by name
  6. Lazy & Func<T> resolution
  7. WhatDoIHave() and other diagnostics — no IoC or any other kind of framework author should release a tool without something like this for the sake of their own sanity
  8. Auto-find missing registrations — one of my biggest gripes about the built in container

Later

  1. Inline dependencies
  2. AutoFactory support — I think this could work out very well with the code generation model
  3. Construction Policies
  4. Some of StructureMap’s attribute configuration

Leaving Behind unless someone else really wants to build *and* help support it

  • Interception — Maybe. I’m not super excited about supporting it
  • Child containers and profiles. Utter nightmare to support. Edge case hell. Crazy amount of complexity internally. The only way we use them in work is for per-test isolation, and we can live without them in that case
  • Changing configuration at runtime (Container.Configure()).
  • Passing arguments at runtime. One of the biggest sources of heartburn for me supporting StructureMap. I think the better autofactory support in BlueMilk could be a far better alternative anyway.

Why do this?

One of my fervent goals with Jasper from the very beginning was to maximize performance to the point where its throughput was barely distinguishable from laboriously writing highly optimized bespoke code by hand. I wanted users to have all the productivity benefits of a good framework that takes care of common infrastructure needs without sacrificing performance. I know that some folks will disagree, but I still think there’s ample reasons to use an IoC container to handle quite a bit of the object composition, service activation, object scoping, and service cleanup.

If you allow that assumption of IoC usage, that left me with a couple options and thoughts:

  • I think it’s hugely disadvantageous to .Net frameworks to have to support multiple IoC containers. My experience is that basically every single framework abstraction I have ever seen for an IoC container has been problematic. If you are going to support multiple IoC containers in your application framework, my experience from FubuMVC and from watching the unfolding consternation over ASP.Net Core’s DI compliance is to restrict your framework from making all but a handful of assumptions about IoC container behavior.
  • I could just use my own StructureMap container because I understand it front to back and it fits the way that I personally work and all the .Net developers in my shop know it. The only problem there is that StructureMap has fallen behind in terms of performance. I think I have a decent handle on what it would take to reverse that with a potential 5.0, but I’m just not up for doing the work, I’m exhausted keeping up with user questions, and I really want to get out of supporting StructureMap.
  • I tried a couple times to just use the new built-in ASP.Net Core DI tool, but it’s extremely limited and I was getting frustrated with how many things were missing and how much more hand holding it took to be usable compared to StructureMap.

If you saw my Jasper’s Special Sauce post last week, you know that we are already using the service registration information to opt into inlining all the object construction and disposal directly into the generated message handlers whenever possible. The code that did that was effectively the beginning of a real IoC container, so it wasn’t that big of a jump to pulling all of that code into its own library and building it into the IoC tool that I wanted a theoretical StructureMap 5.0 to be.

 

Advertisements

Jasper’s Roslyn-Powered “Special Sauce”

As a follow on to my introductory post on the new OSS Jasper messaging framework, here’s an explanation of what’s different about Jasper’s internal approach compared to existing .Net frameworks as well as an argument to why I think it’s a better way.

This is an admittedly long blog post with a lot of background contextual information first. If you’re only here for the “Jasper does crazy stuff with Roslyn” part of it, just skip to the “Special Sauce” section.

In this post, I’m talking about:

  • What makes a tool a framework vs. a library
  • A discussion about the runtime architecture of current .Net frameworks
  • Design challenges for middleware strategies
  • Jasper’s “Special Sauce” approach and why I think it’s a new, better way

What do you mean when you say “Framework?”

First off, Jasper is unmistakably and unapologetically a framework and not just a library. What’s the difference? A library is something your code uses to perform tasks, with the assumption being that your application code is in control and the library code is passive. The Marten persistence tool I work on, logging libraries like NLog or log4net are all examples of library projects. Frameworks on the other hand, follow the Hollywood Principle to handle common workflow events and dealing with technical infrastructure while calling your code just for the actual application logic. Besides Jasper, ASP.Net MVC, NancyFx, or MediatR in the .Net world or Angular.js or Ember.js in the JS world are examples of frameworks (I personally don’t think it’s a clear cut distinction for React on whether or not it’s a framework or a library).

In the case of Jasper, in the process of handling an incoming message it:

  • Logs the arrival of the message
  • Determines from the raw message byte[] array what .Net message type it represents and what deserialization strategy it should use
  • Deserializes the raw data into an actual .Net object that the application code expects
  • Calls any configured middleware for that message type, before finally passing the message to all of the known application handlers for that message type
  • Dispose any IDisposable objects that were created during the message processing
  • Finally, logs the completion, successful or not, and sends out any outgoing messages that “cascaded” from handling the original message if it’s successful
  • If a message fails, process error handling policies to either retry the message, put it back on the queue, stick it into the dead letter queue, or retry it after a delay.

Using Jasper as your messaging framework allows you to focus on just the work that’s specific to your application and let Jasper handle the tedious chores.

The State of the Art in .Net

When a messaging framework needs to process an incoming command or an HTTP framework handles an HTTP request, the common steps are something like this:

  1. Route the incoming data to the proper HTTP route or message type handler
  2. Translate the incoming data to the form that the application handler needs to consume (a message type or a DTO type passed into an HTTP request handler)
  3. Build or find the application specific message or HTTP handlers, along with any other related services
  4. Call the application specific handlers
  5. After the message or HTTP request is complete, do any necessary clean up by disposing services that were created for the request. Stuff like closing and disposing open connections to the database used in handling the message or request.

For right now, let’s focus on 3.) and 4.) up above. We need some way to both discover message handlers or HTTP controllers in the application code and then to execute those handlers or controllers at runtime. I’ve seen and used two different general mechanisms to tackle these issues. The first is to require framework developers to write all their message handlers with some kind of standard interface like this one below:

public interface IHandler
{
    Task Process(T message, Context context);
}

It’s simple to understand, and makes a lot of the underlying mechanics in your framework easier. This strategy is also easy to combine with an IoC container to handle by handler discovery with something like StructureMap’s ConnectImplementationsToTypesClosing type scanning convention. Likewise, using an IoC tool makes object creation, scoping, and cleanup relatively simple. It does have the downside of being a little bit intrusive into application code and it’s not quite as flexible as the next alternative.

The other way to call application code is to use some sort of Reflection to dynamically call handlers. This has the advantage of greater flexibility in how the application specific handlers can be created and possibly reducing coupling from the application specific code to the framework infrastructure. ASP.Net MVC is an example of this approach, as was the earlier FubuMVC project I led earlier. The FubuMVC “hello world” endpoint that would just return text as “string/plain” when the “/” route is called looked like this:

    public class HomeEndpoint
    {
        public string Index()
        {
            return "Hello, world.";
        }
    }

The advantage here is that the code can be subjectively “cleaner,” by which I mean to be an absence of framework artifacts like marker interfaces, mandatory base classes, fluent interfaces, or mandatory attributes. This approach by necessity depends on naming conventions that are frequently derided as “magic” by some folks and when used well, praised as “clean” code by people like me. There’s room in the world for both types of folks.

Another significant advantage is being able to be flexible on the method signatures and even use techniques like “method injection” as ASP.Net Core MVC supports with its [FromServices] attribute in this sample below:

public IActionResult About([FromServices] IDateTime dateTime)
{
    ViewData["Message"] = "Currently on the server the time is " + dateTime.Now;

    return View();
}

From a technical perspective, the challenge is in how you invoke the application handlers if there is no mandatory interface or base class. Traditionally, your options are:

  • Just use Reflection. It’s slow, but it’s the simplest to use
  • Emit dynamic assemblies with IL at runtime. The early versions of StructureMap used that, and I thought it was excruciating. It’s laborious to code and not very approachable for other contributors to your project. I think you get serious neckbeard points for using this successfully.
  • Use .Net Expressions to dynamically generate and compile Lambda’s. StructureMap does this, and I’m guessing that most other .Net IoC tools do as well. AutoMapper does as well. This model is more approachable than IL, but it’s still not something that most .Net developers can — or would want to — use productively. It also creates horrendously awful stack traces in exception messages. If you do use this technique, definitely check out FastExpressionCompiler.

What about middleware?

By this point, any .Net framework worth its salt is going to support what I used to call the Russian Doll Model of nested handlers with something like ASP.Net Core’s (or OWIN’s) concept of middleware. The purpose is to allow developers to move common, cross-cutting concerns like exception handling, validation, or security to middleware and out of each individual message handler or HTTP controller method. Used judiciously, this can make application code simpler and more robust by simply having fewer things for developers to remember to do. Used badly — and trust me, I’ve seen it used horrendously with my very own FubuMVC “behaviors” model — copious usage of middleware will make your application sluggish, potentially hard to understand, and devilishly hard to debug.

One of the common usages of middleware is to manage transactional boundaries between one or more nested handlers like my shop did several years ago in this post with FubuMVC and RavenDb. A sequence diagram of a typical framework’s internal runtime workflow would look something like this:

UoWwithMiddleware

Most .Net frameworks that I’m aware of will use a scope (nested container in StructureMap parlance, IServiceScope in ASP.Net Core, LifetimeScope in Autofac) per message or HTTP request. Using a container scope allows the framework to easily control the scoping of services like a Marten IDocumentSession or an EF DbContext that should be shared by all other services participating in the logical transaction. The container scope usage also allows the framework to clean up resources by calling Dispose() on all the IDisposable objects created during the processing of the message.

As a framework author and as a user of a framework, you’ve got a couple challenges with middleware:

  • Understanding what middleware is applicable to each message type or HTTP route. Sooner or later, it’s going to be necessary to visualize the layers of middleware to debug some problem or other
  • Properly scoping services that are shared between different middleware or the message handlers. ASP.Net Core does this by sharing the container scope as part of the HttpContext and doing a lot of service location at different places in the runtime. FubuMVC and some versions of NServiceBus build the middleware objects and the handlers wrapped inside of them per HTTP request or message being processed. I can tell you from experience helping folks using StructureMap to write ASP.Net Core middleware that their approach can be problematic. The FubuMVC approach was sluggish and did way too many object allocations in memory.
  • The stack traces can be epically bad and noisy, making developer troubleshooting more difficult than it should be
  • Hopefully, the container scope and handler object creation isn’t that expensive, but it’s still object allocations that could be potentially eliminated

Jasper’s Special Sauce

Jasper was largely conceived as a next generation replacement for the earlier FubuMVC framework, and takes a lot of lessons and bias — both positive and negative — from our usage of FubuMVC over the past decade. Roughly speaking, we wanted to support a superset of the message handler signatures (and HTTP endpoint signatures too, but that’s a subject for another day), with the addition of support for method injection of dependencies and support for static methods or classes as well for perfectly stateless handlers. We also wanted to keep roughly the same kind of compose-ability with per message type middleware we had with FubuMVC, but this time be able to provide much more visibility to how the middleware was composed at runtime for easier debugging. At the same time, we knew that FubuMVC suffered from performance problems from the sheer number of objects it created and destroyed in its runtime pipeline. For my personal sanity, I knew that we needed to make the exception stack traces coming out of Jasper have a lot less noise.

Very early on, we theorized that we could heavily use the forthcoming runtime code generation and compilation capability in Roslyn to write the tightest possible “glue” code at runtime that handles the intermediation between the Jasper framework, the associated middleware, and the application handlers.

The actual message handlers activated and executed by Jasper’s internal pipeline all inherit from this base class:

    public abstract class MessageHandler
    {
        // Error handling policies for the message type
        // and other configuration kind of things that
        // the Handle method might need
        public HandlerChain Chain { get; set; }

        // This method actually processes the incoming Envelope
        public abstract Task Handle(IInvocationContext input);
    }

Removing the actual middleware noise cleaned up the exception stack traces dramatically. Surfacing the generated code up to users serves as a cheap, but effective visualization of what’s going on internally for developers. Finally, we were sure that this strategy would greatly improve our performance by drastically reducing memory allocations and method delegations in our internals. And wouldn’t you know it, the NServiceBus team who had earlier borrowed FubuMVC’s “Behavior” model, made the same kind of change to using generated code (but with Expression’s) and reported an absurd improvement in their measured performance. Jasper uses a similar approach to NServiceBus 6, but I think we go much farther and that our code generation model will be much more approachable to outsiders than having to deal with Expressions.

In the next section I’ll show what the code generation does, and talk about how to write the fastest possible code with Jasper.

Sample Messaging Scenario

To see the code generation in action, let’s say that we need to handle a CreateItemCommand message, and save a corresponding ItemCreatedEvent document using Marten as our backing store.

The command and event objects look like this:

    public class CreateItemCommand
    {
        public string Name { get; set; }
    }

    public class ItemCreatedEvent
    {
        public Item Item { get; set; }
    }

In its crudest form, the message handler in Jasper using a traditional class instance that takes all of its dependencies in via constructor injection:

    public class CreateItemHandler
    {
        private readonly IDocumentStore _store;

        // store is the Marten IDocumentStore
        public CreateItemHandler(IDocumentStore store)
        {
            _store = store;
        }

        public async Task Handle(CreateItemCommand command)
        {
            using (var session = _store.LightweightSession())
            {
                var item = new Item {Name = command.Name};
                session.Store(item);
                await session.SaveChangesAsync();
            }
        }
    }

At runtime, Jasper will generate this code for the actual MessageHandler:

    public class ShowHandler_CreateItemCommand : Jasper.Bus.Model.MessageHandler
    {
        private readonly IDocumentStore _documentStore;

        public ShowHandler_CreateItemCommand(IDocumentStore documentStore)
        {
            _documentStore = documentStore;
        }


        public override Task Handle(Jasper.Bus.Runtime.Invocation.IInvocationContext context)
        {
            var createItemHandler 
                = new ShowHandler.CreateItemHandler(_documentStore);
            var createItemCommand = (ShowHandler.CreateItemCommand)context.Envelope.Message;
            return createItemHandler.Handle(createItemCommand);
        }

    }

Notice anything missing here from the “typical” framework pipeline I talked about in previous sections? That missing thing is any trace whatsoever of an IoC container at runtime. It turns out that the very fastest IoC container for object resolution is no container. With that in mind, any time that Jasper can figure out from the underlying service registrations how to do all the object construction and disposal per message inside of the generated Handle() method, it will not use the IoC container whatsoever. While there are plenty of cases that Jasper can’t quite handle yet and has to resort to generate code that does service location, we’re working very hard to close those gaps.

There’s a couple other things to note in the code up above:

  • The MessageHandler objects are compiled and created at runtime, and they are singleton scoped inside the application
  • The IDocumentStore dependency is known to be a singleton in the service registrations, so it is injected into the MessageHandler during its construction so there doesn’t have to be any kind of service lookup for that at runtime

Jasper can also support method injection of service dependencies in the message handler actions, so we could just pull in IDocumentStore as a method argument and simplify the code a little bit. Once you do that though, the ShowHandler class is entirely stateless, so let’s go a little bit farther and just make ShowHandler a static class like so:

    public static class CreateItemHandler
    {
        public static async Task Handle(CreateItemCommand command, IDocumentStore store)
        {
            using (var session = store.LightweightSession())
            {
                var item = new Item {Name = command.Name};
                session.Store(item);
                await session.SaveChangesAsync();
            }
        }
    }

Okay, the “static” keyword is a little bit of noise, but we got rid of the private field for the store and the constructor function, so it’s a little bit tighter. Using that handler above will result in Jasper generating this code:

    public class ShowHandler_CreateItemCommand : Jasper.Bus.Model.MessageHandler
    {
        private readonly IDocumentStore _documentStore;

        public ShowHandler_CreateItemCommand(IDocumentStore documentStore)
        {
            _documentStore = documentStore;
        }


        public override Task Handle(Jasper.Bus.Runtime.Invocation.IInvocationContext context)
        {
            var createItemCommand = (ShowHandler.CreateItemCommand)context.Envelope.Message;
            return ShowHandler.CreateItemHandler.Handle(createItemCommand, _documentStore);
        }

    }

The key thing up above being that switching to a static method in our message handler means one less object allocation for the message handler objects.

Finally, the one single bit of middleware that we built to prove out this whole strategy just happens to be some Marten transactional support. There are other ways to apply the middleware, but for right now I’ll just decorate the method with a [MartenTransaction] attribute from the Jasper.Marten library to apply that middleware handling around the handler. For fun, let’s even say that the act of handling the command emits a new event message that will be “cascaded” as an outgoing message when the original message has been completely processed. To do that, just return the event from your handler method. If the middleware is handling the call to IDocumentSession.SaveChangesAsync()/RollbackAsync() for me, I can simplify the message handler code in my application down even further to this now:

    public class CreateItemHandler
    {
        [MartenTransaction]
        public static ItemCreatedEvent Handle(
            CreateItemCommand command, 
            IDocumentSession session)
        {
            var item = new Item {Name = command.Name};
            session.Store(item);

            return new ItemCreatedEvent{Item = item};
        }
    }

If you notice, we’re able to use a synchronous method signature here instead of being forced to repetitively all return Task.CompletedTask; every which way because Jasper is smart enough to handle those mechanics for us in its code generation. It’s even smart enough to (imperfectly) switch from a method with an “async Task” signature to a method that can return a Task from the last line of code or “Task.CompletedTask.”

The handler above, with the Marten transaction middleware wrapped in, gives us this compiled code:

    public class ShowHandler_CreateItemCommand : Jasper.Bus.Model.MessageHandler
    {
        private readonly IDocumentStore _documentStore;

        public ShowHandler_CreateItemCommand(IDocumentStore documentStore)
        {
            _documentStore = documentStore;
        }


        public override async Task Handle(Jasper.Bus.Runtime.Invocation.IInvocationContext context)
        {
            var createItemCommand = (ShowHandler.CreateItemCommand)context.Envelope.Message;
            using (var documentSession = _documentStore.OpenSession())
            {
                var outgoing1 = ShowHandler.CreateItemHandler.Handle(createItemCommand, documentSession);
                context.EnqueueCascading(outgoing1);
                await documentSession.SaveChangesAsync();
            }

        }

    }

So, yeah, there’s some magic going on with conventions that some folks absolutely hate, but if it’s easy to get at the generated code internally and you can just read and even debug into that, are conventions really that scary anymore?

Our hope is that the code generation model leads to applications written with Jasper being just as performant as purely bespoke code, but with far less effort on the developer’s part. We think that our runtime codegen model gives Jasper the best of all possible worlds by allowing for very clean, flexible code without sacrificing anything in terms of performance.

It’s a ways away, but I’m well underway in the process of ripping the code generation support out into its own library under the BlueMilk moniker and growing that into a streamlined, performant replacement for StructureMap as well. I’ll blog next week about the vision and maybe the timeline for BlueMilk by itself.

Introducing Jasper — Asynchronous Messaging for .Net

IMG_1017

For my take on when you would use a tool like Jasper, see How Should Microservice’s Communicate?

“Jasper” is the codename for a new messaging and command execution framework that my shop has been building out to both integrate with and eventually replace our existing messaging infrastructure as we migrate applications to Netstandard 2.0, ASP.Net Core, and yes, adopt a microservices architecture. While we’ve been working very hard on it over the past 6 months, I’ve been hesitant to talk about it too much online. That ends today with the release of the first usable alpha (0.5.0) to Nuget today.

We’ve already done a great deal of work and it’s fairly feature rich, but I’m really just hoping to start drumming up some community interest and getting whatever feedback I can. Production-worthy versions of Jasper should hopefully be ready this spring.

Okay, so what problems does it solve over just using queues?

It’s ostensibly about NServiceBus (for right now, let’s call that the most similar competitor to Jasper), but Sure, You Can Just Use RabbitMQ sums it up perfectly. Jasper already supports functionality to:

Why would you want to use Jasper over [fill in the blank tool]?

I hate this part of talking about any kind of OSS activity or choice, but I know it’s coming, so let’s get to it:

  • Jasper’s execution pipeline is leaner than any other .Net framework that I’m aware of, and we’re theorizing that this will lead to Jasper having better performance, less memory utilization, less GC thrashing, and easier to understand stacktraces than other .Net frameworks. My very next blog post will be showing off our “special sauce” usage of Roslyn code generation and runtime compilation that makes this all possible.
  • Jasper requires much less coupling from your application code to the framework, especially compared to the typical .Net framework that requires you to implement their own interfaces or base classes, tangle your code with fluent interfaces, or force you to spray attributes all over your code. Some of you aren’t going to like that, but my preference is always cleaner code. There’s plenty of room in the world for both of us;)
  • It’s FOSS
  • Jasper plays nicely with ASP.Net Core and even comes with recipes for quick integration into ASP.Net Core applications

Ping/Pong Hello World

The obligatory “hello, world” project in messaging is to send a “ping” message from one service to another, with the expectation that the receiving system will send back a “pong.” So let’s start by saying we have a couple message types like these:

    public class PingMessage
    {
        public string Name { get; set; }
    }

    public class PongMessage
    {
        public string Name { get; set; }
    }

Note: Jasper does not require you to share .Net types between systems, but it’s the easiest way to get started so here you go.

Starting with the “Ponger” service (if the code is cut off in the blog post, it’s all in this project on GitHub), just follow these steps:

  1. “dotnet new console” to create a new console app
  2. Add a Nuget reference to Jasper.CommandLine that will also bring in the core Jasper Nuget as well

From there, the entire “Ponger” service is the following code:

    class Program
    {
        static int Main(string[] args)
        {
            return JasperAgent.Run(args, _ =>
            {
                _.Logging.UseConsoleLogging = true;

                _.Transports.LightweightListenerAt(2601);
            });
        }
    }

    public class PingHandler
    {
        public object Handle(PingMessage message)
        {
            ConsoleWriter.Write(ConsoleColor.Cyan, "Got a ping with name: " + message.Name);

            var response = new PongMessage
            {
                Name = message.Name
            };

            // Send a Pong response back to the original sender
            return Respond.With(response).ToSender();
        }
    }

Now, moving on to the “Pinger” service. Follow the same steps to start a new .Net console project and add a reference to the Jasper.CommandLine Nuget.

From there, we can utilize ASP.Net Core’s support for background services to send a new ping message every second:

    public class PingSender : BackgroundService
    {
        private readonly IServiceBus _bus;

        public PingSender(IServiceBus bus)
        {
            _bus = bus;
        }

        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            int count = 1;

            return Task.Run(async () =>
            {
                while (!stoppingToken.IsCancellationRequested)
                {
                    Thread.Sleep(1000);

                    await _bus.Send(new PingMessage
                    {
                        Name = "Message" + count++
                    });
                }
            }, stoppingToken);
        }
    }

Next, we need a simple message handler that receives the pong replies and writes the receipt to the console output:

    // Handles the Pong responses
    public class PongHandler
    {
        public void Handle(PongMessage message)
        {
            ConsoleWriter.Write(ConsoleColor.Cyan, "Got a pong back with name: " + message.Name);
        }
    }

Now, there’s a little more work to configure the Pinger application:

    class Program
    {
        static int Main(string[] args)
        {
            return JasperAgent.Run(args, _ =>
            {
                // Way too verbose logging suitable
                // for debugging
                _.Logging.UseConsoleLogging = true;

                // Listen for incoming messages
                // at port 2600
                _.Transports.LightweightListenerAt(2600);

                // Using static routing rules to start
                _.Publish.Message()
                    .To("tcp://localhost:2601");

                // Just adding the PingSender
                _.Services.AddSingleton<IHostedService, PingSender>();
            });
        }
    }

If I start up the Pinger application with “dotnet run” at the command line, I get output like this:

Running service 'Pinger'
Application Assembly: Pinger, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Hosting environment: Production
Content root path: /Users/user/code/jasper/src/Pinger/bin/Debug/netcoreapp2.0/
Listening for loopback messages
Listening at tcp://YOURMACHINE:2600/

Active sending agent to ws://default/
Active sending agent to tcp://localhost:2601/
Active sending agent to loopback://replies/
Active sending agent to loopback://retries/
Application started. Press Ctrl+C to shut down.

Which, because the Ponger application hasn’t been started, will start spitting out messages like:

Failure trying to send a message batch to tcp://localhost:2601/

And after enough failures trying to send messages, you’ll finally see this:

Sending agent for tcp://localhost:2601/ is latched

Now, after starting the Ponger service with its own “dotnet run,” you should see the following output back in the Pinger console output after Jasper detects that the downstream system for the Ping messages is available:

Sending agent for tcp://localhost:2601/ has resumed

And finally, a whole bunch of console messages about ping and pong messages zipping back and forth.

Other Common Questions

  • Is this in production yet? Yes, a super, duper early version of Jasper is in production in a low volume system.
  • Is it ready for production usage? No, it’s not really proven out yet in real usage. I think we’ll be able to start converting applications to Jasper this month, so it hopefully won’t be long. The sooner that folks poke and prod it, then supply feedback, the faster it’s ready to go.
  • What .Net frameworks does it support? Netstandard 2.0 only.
  • Where’s the code? On GitHub.
  • Are there any docs yet? Yeah, but there’s plenty of room for improvement on the Jasper website.
  • Where can I ask questions or just make fun of this thing? There’s a Gitter room ready
  • What about the license? The permissive MIT license.
  • Is it just you? Nope, several of my colleagues have contributed code, ideas, and feedback so far.
  • Do you want more contributors? Hell, yeah. The more the merrier.
  • Why roll your own? See the first section of this post. We’re not starting from scratch by any means, otherwise I don’t think we would have opted to build something brand new.
  • What’s with the boring name? It’s my hometown, it’s easy to remember, and it can’t possibly offend anyone like “fubu” did.
  • What’s the story with IoC integration? Uh, yeah, it’s StructureMap 4.5 only just at the moment, but that’s a much longer discussion for another blog post. A huge design goal of Jasper is to try to minimize the usage of an IoC container outside of the initial bootstrapping and application shutdown, so I’m not sure you’re going to care all that much.

What’s next?

I’m actually slowing down on new development on Jasper for awhile, but I’ll be flooding the interwebs with blog posts on Jasper while I also plug holes in the documentation. The next big thing at work is to start the trial conversion of one of our applications to Jasper. For longer term items in our backlog, just see the GitHub issue list. The next development task is probably going to have to be replicating the integration we’ve done with Postgresql and Marten for Sql Server.

RabbitMQ, Kafka, and Azure Service Bus integrations will follow later this year.

Publish / Subscribe Messaging in our Ecosystem

Long story short, several of my colleagues and I are building a new framework for managing asynchronous messaging between .Net services with the codename “Jasper” as a modernized replacement for our existing FubuMVC based messaging infrastructure. Once I get a good couple weeks of downtime during the holidays, I’ll be making the first big public alpha nuget of Jasper and start blogging up a storm about the project, but for right now, here’s this post about Jasper’s intended dynamic subscription model.

As part of our larger effort at work to move toward a microservices architecture, some of us did a big internal presentation last week about the progress so far in our new messaging infrastructure we intend to use next year as we transition to Netstandard2 and all the modern .Net stuff. I went over my time slot before we could talk about our proposal for how we plan to handle publish/subscribe messaging and service discovery. I promised this post in the hopes of getting some feedback.

The Basic Architecture

Inside of our applications, when we need to publish or send a message to other systems, we would use some code like this:

public Task SendMessage(IServiceBus bus)
{
    // In this case, we're sending an "InvoiceCreated"
    // message
    var @event = new InvoiceCreated
    {
        Time = DateTime.UtcNow,
        Purchaser = "Guy Fieri",
        Amount = 112.34,
        Item = "Cookbook"
    };

    // Mandatory that there is subscribers for this message
    return bus.Send(@event);

    // or send the message to any subscribers for this type
    // of message, but don't enforce the existence of any
    // subscribers
    return bus.Publish(@event);
    
}

The system publishing messages itself doesn’t need to know or even how to send that message to whatever the downstream system is. The infrastructure code underneath bus.Send() knows how to look up any registered subscribers for the “InvoiceCreated” event message in some kind of subscription storage and route the message accordingly.

The basic architecture is shown below:

subscriptions

Just to make this clear, there’s no technical reason why the “subscription storage” has to be a shared resource — and therefore a single point of failure — between the systems.

Now that we’ve got the barebones basics, here are the underlying problems we’re trying to solve to make that diagram above work in real life.

The Problem Statement

Consider a fairly large scale technical ecosystem composed of many services that need to work together by exchanging messages in an asynchronous manner. You’ve got a couple challenges to consider:

  • How do the various applications “know” where and how to send or publish messages?
  • How do you account for the potential change in message payloads or representations between systems?
  • How could you create a living document that accurately describes how information flows between the systems?
  • How can you add new systems that need to publish or receive messages without having to do intrusive work on the existing systems to accomodate the new system?
  • How might you detect mismatches in capabilities between all the systems without having to just let things blow up in production?

Before I lay out our working theory about how we’ll do all of the above in our development next year, let’s talk about the downsides of doing all of that very badly. When I was still wet behind the ears as a developer, I worked at a very large manufacturing company (one of the “most admired” companies in the US at the time) that had an absolutely wretched “n-squared” problem where integration between lots of applications was done in an ad hoc manner with more or less hard coded, one off mechanisms between applications. Every time we needed a new integration, we had to effectively do all new work and break into all of the applications involved in the new data exchange.

I survived that experience with plenty of scars and I’m sure many of you have similar experiences. To solve this problem going forward, my shop has come up with the “dynamic subscription” model (the docs in that link are a bit out of date) in our forthcoming “Jasper” messaging framework.

Our Proposed Goals and Approach

A lot of this is already built out today, but it’s not in production yet and now’s a perfect time for feedback (hint, hint colleagues of mine). The primary goals in the Jasper approach is to:

  • Eliminate any need for a central broker or any other kind of single point of failure
  • Reduce direct coupling and between services
  • Make it easy to update, browse, or delete subscriptions
  • Provide tooling to validate the subscriptions across services
  • Allow developers to quickly visualize how messages flow in our ecosystem between senders and receivers

Now, to put this into action. First, each application should declare the messages it needs to subscribe to with code like this:

    public class MyAppRegistry : JasperRegistry
    {
        public MyAppRegistry()
        {
            // Override where you want the incoming messages
            // to be sent.
            Subscribe.At("tcp://server1:2222");

            // Declare which messages this system wants to 
            // receive
            Subscribe.To();
            Subscribe.To();
        }
    }

Note: the “JasperRegistry” type fulfills the same role for configuring a Jasper application as the WebHostBuilder and Startup classes do in ASP.Net Core applications.

When the application configured by the “MyAppRegistry” shown above is bootstrapped, it calculates its subscription requirements that include:

  • The logical name of the message type. By default this is derived from the .Net type, but doesn’t have to be. We use the logical name to avoid forcing you to share an assembly with the DTO message types
  • All of the representations of the message type that this application understands and can accept. This is done to enable version messaging between our applications and to enable alternative serialization or even custom reading/writing strategies later
  • The server address where the upstream applications should send the messages. We’re envisioning that this address will be the load balancer address when we’re hosting on premises in a single data center, or left blank for when we get to jump to cloud hosting when we’ll do some additional work to figure out the network address of the subscriber that’s most appropriate within the data center where the sender is hosted.

At deployment time, whenever a service is going to be updated, our theory is that you’ll have a step in your deployment process that will publish the subscription requirements to the proper subscription storage. If you’re using the built in command line support, and your Jasper application compiles to an executable called “MyApp.exe,” you could use this command line signature to publish subscriptions:

MyApp.exe subscriptions publish

At this point, we’re working under the assumption that we’ll be primarily using Consul as our subscription storage mechanism, but we also have a Postgresql-backed option as well. We think that Consul is a good fit here because of the way that it won’t create a single point of failure while also allowing us to replicate the subscription information between nodes through its own gossip protocol.

Validating Subscriptions

To take this capability farther, Jasper will allow you to declare what messages are published by a system like so:

    public class MyAppRegistry : JasperRegistry
    {
        public MyAppRegistry()
        {
            Publish.Message();
            Publish.Message();
            Publish.Message();
        }
    }

Note: You can also use an attribute directly on the published message types if you prefer, or use a convention for the braver.

When a Jasper application starts up, it combines the declaration of published message types with the known representations or message versions found in the system, and combines that information with the subscription requirements into what Jasper calls the “ServiceCapabilities” model (think of this as Swagger for Jasper messaging, or OpenAPI just in case Darrel Miller ever reads this;)).

Again, if your Jasper application compiles through dotnet publish to a file called “MyApp.exe”, you’ll get a couple more command line functions. First, to dump a JSON representation of the service to a file system folder, you can do this:

MyApp.exe subscriptions export --directory ~/subscriptions

My thinking here was that you could have a Git repository where all the services export their service capabilities at deployment time, because, that would enable you to use this command later:

MyApp.exe subscriptions validate --file subscription-report.json

The command above would read in all the service capability files in that directory, and analyze all the known message publishing and subscriptions to create a report with:

 

  1. All the valid message routes from sender to receiver by message type, the address of the receiver, and the representation or version of the message
  2. Any message types that are subscribed to, but not published by any service
  3. Message types that are published by one or more services, but not subscribed to by any other system
  4. Invalid message routing through mismatches in either accepted or published versions or transport mismatches (like if the sender can send messages only through TCP, but the receiver can only receive via HTTP)

Future Work

I thought we were basically done with this feature, but it’s not in production yet and we did come up with some additional items or changes before we go live:

  • Build a subscription control panel that’ll be a web front end that allows you to analyze or even edit subscriptions in the subscription storage
  • Publish the full service capabilities to the subscription storage (we only publish the subscriptions today)
  • Get a bit more intelligent with Consul and how we would use message routing if running nodes of the named services are hosted in different data centers
  • Create the idea of message “ownership,” as in “only this system should be processing this command message type”
  • Some kind of cache busting in the running Jasper nodes to refresh the subscription information in memory whenever the subscription storage changes

Jasper’s Getting Started Story – Take 1

IMG_1017

I’ve been kicking around the idea for a possible resurrection of FubuMVC as a mostly new framework with the codename “Jasper”  for several years with some of my colleagues. This year myself and several members of our architecture team at work have started making that a reality as the centerpiece of our longer term microservices strategy.

In the end, Jasper will be a lightweight service bus for asynchronous messaging, a high performance alternative to MVC for HTTP API’s, and a substitute for MediatR inside of ASP.Net Core applications (those three usages share much more infrastructure code than you might imagine and the whole thing is still going to be much, much smaller than FubuMVC was at the end). For the moment, we’re almost entirely focused on the messaging functionality.

I haven’t kicked out an up to date Nuget yet, but there’s quite a bit of documentation and I’m just hoping to get some feedback out of that right now. If you’re at all interested in Jasper, feel free to raise GitHub issues or join our Gitter room.

The only thing I’m trying to accomplish in this post is to get a sanity check from other folks on whether or not the bootstrapping looks usable.

Getting Started

This is taken directly from the getting started documentation.

Note! Jasper only targets Netstandard 1.5 and higher at this time, and we’ve been holding off on upgrading to ASP.Net Core v2.0.

Jasper is a framework for building server side services in .Net. Jasper can be used as an alternative web framework for .Net, a service bus for messaging, as a “mediator” type pipeline within a different framework, or any combination thereof. Jasper can be used as either your main application framework that handles all the configuration and bootstrapping, or as an add on to ASP.Net Core applications.

To create a new Jasper application, start by building a new console application:

dotnet new console -n MyApp

While this isn’t expressly necessary, you probably want to create a new JasperRegistry that will define the active options and configuration for your application:

public class MyAppRegistry : JasperRegistry
{
    public MyAppRegistry()
    {
        // Configure or select options in this constructor function
    }
}

See Configuring Jasper Applications for more information about using the JasperRegistry class.

Now, to bootstrap your application, add the Jasper.CommandLine library to your project and this code to the entrypoint of your console application:


using Jasper.CommandLine;

namespace MyApp
{
    class Program
    {
        static int Main(string[] args)
        {
            // This bootstraps and runs the Jasper
            // application as defined by MyAppRegistry
            // until the executable is stopped
            return JasperAgent.Run<MyAppRegistry>(args);
        }
    }
}

By itself, this doesn’t really do much, so let’s add Kestrel as a web server for serving HTTP services and start listening for messages from other applications using Jasper’s built in, lightweight transport:

public class MyAppRegistry : JasperRegistry
{
    public MyAppRegistry()
    {
        Http.UseKestrel().UseUrls("http://localhost:3001");
        Transports.Lightweight.ListenOnPort(2222);
    }
}

Now, when you run the console application you should see output like this:

Hosting environment: Production
Content root path: /Users/jeremill/code/jasper/src/MyApp/bin/Debug/netcoreapp1.1
Listening for messages at loopback://delayed/
Listening for messages at jasper://localhost:2333/replies
Listening for messages at jasper://localhost:2222/incoming
Now listening on: http://localhost:3001
Application started. Press Ctrl+C to shut down.

See Bootstrapping for more information about idiomatic Jasper bootstrapping.

That covers bootstrapping Jasper by itself, but next let’s see how you can add Jasper to an idiomatic ASP.Net Core application.

Adding Jasper to an ASP.Net Core Application

If you prefer to use typical ASP.Net Core bootstrapping or want to add Jasper messaging support to an existing project, you can use the UseJasper() extension method on ASP.Net Core’s IWebHostBuilder as shown below:

var host = new WebHostBuilder()
    .UseKestrel()
    .UseJasper<ServiceBusApp>()
    .Build();

host.Run();

See Adding Jasper to an ASP.Net Core Application for more information about configuring Jasper through ASP.Net Core hosting.

Your First HTTP Endpoint

The obligatory “Hello World” http endpoint is just this:

public class HomeEndpoint
{
    public string Get()
    {
        return "Hello, world.";
    }
}

As long as that class is in the same assembly as your JasperRegistry class, Jasper will find it and make the “Get” method handle the root url of your application.

See HTTP Services for more information about Jasper’s HTTP handling features.

Your First Message Handler

Let’s say you’re building an invoicing application and your application should handle an InvoiceCreated event. The skeleton for the message handler for that event would look like this:

public class InvoiceCreated
{
    public Guid InvoiceId { get; set; }
}

public class InvoiceHandler
{
    public void Handle(InvoiceCreated created)
    {
        // do something here with the created variable...
    }
}

See Message Handlers for more information on message handler actions.

 

 

Message Handlers in the new Jasper Service Bus

A couple months ago I blogged a little bit about a yet another OSS service bus project my shop is building out for messaging in .Net Core systems called Jasper that services as a wire compatible successor to the tooling we use in older .Net applications. While it’s already in production systems at work and doing fine, I have no clue if it’ll have any success as an OSS project. At the very least I’m going to squeeze some blog posts out of the process of building it and here we are.

Service bus frameworks are definitely an example of the Hollywood Principle where a framework handles much of the event handling and workflow while delegating to your application specific code through some kind of interface or idiom. In most of the cases I’ve seen over the years in .Net, you’ll see some kind of interface like the one below that allows you to plug your message handlers into your service bus infrastructure:

public interface IHandler
{
    Task Handle(T message);
}

I’ve certainly used this approach in a handful of cases, and there’s even some direct support for auto-registering this kind of service strategy inside of StructureMap if you want to roll your own framework. It’s easy to understand, adds some level of discoverability, and might help guide users. It’s also somewhat limiting in flexibility and the copious usage of generics can easily lead users into some bad places — and I say that partially based on a decade of helping folks with generics on the StructureMap user lists.

Jasper takes a different approach that relies much more on naming conventions and method signatures. To make that concrete, here’s the very simplest form of message handlers you can use in Jasper and if you don’t mind, let me leave how could this possibly work efficiently for a followup post (spoiler alert: Roslyn is awesome):

public class ExampleHandler
{
    public void Handle(Message1 message)
    {
        // Do work synchronously
    }

    public Task Handle(Message2 message)
    {
        // Do work asynchronously
        return Task.CompletedTask;
    }
}

Out of the box, Jasper finds and uses message handling methods by searching for concrete classes whose names are suffixed with either “Handler” or “Consumer” (there’s some historical reasons for having both) and then discovers message handling actions by analyzing the public methods on those classes for message handling candidates.

Right off the bat, you can see that Jasper allows you to write either synchronous or asynchronous methods to handle messages, so no more phantom “return Task.CompletedTask;” lines cluttering up your code.

Moreover, you can wring out a little more performance in your system by using static methods instead:

public static class StaticHandler
{
    public static Task Handle(Message3 message)
    {
        return Task.CompletedTask;
    }
}

It might be advantageous to use this approach to reduce memory allocations at run time and should give you slightly more efficient IL. Of course, any handler method, static or otherwise, isn’t terribly helpful unless you can get at the services within your application that you’ll need to invoke to process the message.

To that end Jasper gives you a couple possibilities. First, you can do the idiomatic, constructor injection approach like this:

public class ServiceUsingHandler
{
    private readonly IService _service;

    public ServiceUsingHandler(IService service)
    {
        _service = service;
    }

    public void Handle(Message1 message)
    {
        // do something with _service to handle this thing
    }
}

At the moment, Jasper would revert to spinning up a StructureMap nested container and uses that to build out the ServiceUsingHandler objects something like this:

// _root is a reference to the application's root
// container
using (var nested = _root.GetNestedContainer())
{
    var serviceUsingHandler = nested.GetInstance();
    var message1 = (Message1)context.Envelope.Message;
    serviceUsingHandler.Handle(message1, widget);
}

Using that approach enables Jasper to build objects of your handler classes with whatever dependencies you would need. Alternatively, you can also use “method injection” in your handlers like this:

public void Handle(
    Message2 message, 
    IService service, 
    Envelope envelope
)
{
    // handle the message
}

In the example above, Jasper “knows” how to resolve both the IService and Envelope dependencies before calling into the Handle() method. The Envelope object is Jasper’s version of an envelope wrapper that gives you more metadata about the current message. Instead of pushing everything through the constructor function, you can opt for potentially simpler and cleaner code by opting for method injection instead. In the case of the Envelope, that is not even available through the IoC container.

More about this in a later post, but ironically as the author of literally the oldest IoC container in .the .Net ecosystem, I’m trying hard to reduce Jasper’s usage of IoC containers at runtime.

The last thing I wanted to show here was Jasper’s concept of cascading messages that we used with some success in the earlier FubuMVC service bus. It’s very common for the handling of the original message to trigger additional “cascading” messages. In most service bus frameworks, that’d probably be something like this:

public class MessageHandler
{
    // Successfully handling Message1 will generate
    // a Message2 going out
    public Message2 Handle(Message1 message, IServiceBus bus)
    {
        bus.Send(new Message2());
    }
}

You can absolutely do that in Jasper as well, but we also support a policy where object(s) returned from a handler method are considered to be outgoing messages that are sent out as part of considering the message request complete. In its simplest usage, that may look like this:

public class MessageHandler
{
    // Successfully handling Message1 will generate
    // a Message2 going out
    public Message2 Handle(Message1 message)
    {
        return new Message2();
    }

    // Same thing, but async
    public Task Handle(Message1 message)
    {
        
    }
}

To get a little more complex, let’s say that your neck deep in CQRS jargon and when your service receives a “Command1” you raise one or more domain events that are handled separately. With cascading messages, that can look like this:

public IEnumerable<object> Handle(Command1 command)
{
    yield return new Event1();
    yield return new Event2();
}

In this case, each object returned is an outgoing message. I like the cascading message approach because it makes your message handlers easier to test with pure state-based testing.

There’s plenty more going on with this feature, but my wife really needs me to get out the office to go help with the little ones, so there’s going to have to more later;)

A way too early discussion of “Jasper”

After determining that I wasn’t going to be able to easily move the old FubuMVC codebase to the CoreCLR, I’ve been furiously working on the long proposed and delayed successor to FubuMVC that’s going to be called “Jasper.” I’m trying to get in front of a team doing CoreCLR development at work with a working MVP feature set in the next couple weeks. I’m needing to bring a couple other folks from my shop on to help out and a few folks have been asking what I’m up to just because of the sudden flurry of Github activity, so here’s a big ol’ braindump of the roadmap and architectural direction so far.

First, why do this at all instead of switching to another existing service bus?

  1. We’re happy with how FubuMVC’s service bus support has worked out
  2. We need to be “wire compatible” with FubuMVC
  3. We want to do CoreCLR development right now, and NSB/MassTransit isn’t there yet
  4. Jasper will be “xcopy deployable,” which we’ve found to be very advantageous for both development and automated testing
  5. Because I want to — but don’t let my boss hear that

The Vision

Jasper is a next generation application development framework for distributed server side development in .Net (think service bus now and HTTP services later). Jasper is being built on the CoreCLR as a replacement for a small subset of the older FubuMVC tooling. Roughly stated, Jasper intends to keep the things that have been successful in FubuMVC, ditch the things that weren’t, and make the runtime pipeline be much more performant. Oh, and make the stack traces from failures within the runtime pipeline be a whole lot simpler to read — and yes, that’s absolutely worth being one of the main goals.

The current thinking is that we’d have these libraries/Nugets:

  1. Jasper – The core assembly that will handle bootstrapping, configuration, and the Roslyn code generation tooling
  2. JasperBus – The service bus features from FubuMVC and an alternative to MediatR
  3. JasperDiagnostics – Runtime diagnostics meant for development and testing
  4. JasperStoryteller – Support for hosting Jasper applications within Storyteller specification projects.
  5. JasperHttp (later) – Build HTTP micro-services on top of ASP.Net Core in a FubuMVC-esque way.
  6. JasperQueues (later) – JasperBus is going to use LightningQueues as its
    primary transport mechanism, but I’d possibly like to re-architect that code to a new library inside of Jasper. This library will not have any references or coupling to any other Jasper project.
  7. JasperScheduler (proposed for much later) – Scheduled or polling job support on top of JasperBus

The Core Pipeline and Roslyn

The basic goal of Jasper is to provide a much more efficient and improved version of the older FubuMVC architecture for CoreCLR development that is also “wire compatible” with our existing FubuMVC 3 services on .Net 4.6.

The original, core concept of FubuMVC was what we called the Russion Doll Model and is now mostly refered to as middleware. The Russian Doll Model architecture makes it relatively easy for developers to reuse code for cross cutting concerns like validation or security without having to write nearly so much explicit code. At this point, many other .Net frameworks support some kind of Russian Doll Model architecture like ASP.Net Core’s middleware or the Behavior model in NServiceBus.

In FubuMVC, that consisted of a couple parts:

  • A runtime abstraction for middleware called IActionBehavior for every step in the runtime pipeline for processing an HTTP request or service bus message. Behavior’s were a linked list chain from outermost behavior to innermost. This model was also adapted from FubuMVC into NServiceBus.
  • A configuration time model we called the BehaviorGraph that expressed all the routes and service bus message handling chains of behaviors in the system. This configuration time model made it possible to apply conventions and policies that established what exact middleware ran in what order for each message type or HTTP route. This configuration model also allowed FubuMVC to expose diagnostic visualizations about each chain that was valuable for troubleshooting problems or just flat out understanding what was in the system to begin with.

Great, lots of flexibility and some unusual diagnostics, but the FubuMVC model gets a lot uglier when you go to an “async by default” execution pipeline. Maybe more importantly, it suffers from too many object allocations because of all the little objects getting created on every message or HTTP request that hurt performance and scalability. Lastly, it makes for some truly awful stack traces when things go wrong because of all the bouncing between behaviors in the nested handler chain.

For Jasper, we’re going to keep the configuration model (but simplified), but this time around we’re doing some code generation at runtime to “bake” the execution pipeline in a much tighter package, then use the new runtime code compilation capabilitites in Roslyn to generate assemblies on the fly.

As part of that, we’re trying every possible trick we can think of to reduce object allocations and minimize the work being done at runtime by the underlying IoC container. The NServiceBus team did something very similar with their version of middleware and claimed an absolutely humongous improvement in throughput, so we’re very optimistic about this approach.

What’s with the name?

I think that FubuMVC turned some people off by its name (“for us, by us”). This time around I was going for an unassuming name that was easy to remember and just named it after my hometown (Jasper, MO).

JasperBus

The initial feature set looks to be:

  • Running decoupled commands ala MediatR
  • In memory transport
  • LightningQueues based transport
  • Publish/Subscribe messaging
  • Request/Reply messaging patterns
  • Dead letter queue mechanics
  • Configurable error handling rules
  • The “cascading messages” feature from FubuMVC
  • Static message routing rules
  • Subscriptions for dynamic routing — this time we’re looking at using [Consul(https://www.consul.io/)] for the underlying storage
  • Delayed messages
  • Batch message processing
  • Saga support (later) — but this is going to be a complete rewrite from FubuMVC

There is no intention to add the polling or scheduled job functionality that was in FubuMVC to Jasper.

JasperDiagnostics

We haven’t detailed this one out much, but I’m thinking it’s going to be a completely encapsulated ASP.Net Core application using Kestrel to serve some diagnostic views of a running Jasper application. As much as anything, I think this project is going to be a test bed for my shop’s approach to React/Redux and an excuse to experiment with the Apollo client with or without GraphQL. The diagnostics should expose both a static view of the application’s configuration and a live tracing of messages or HTTP requests being handled.

JasperStoryteller

This library won’t do too much, but we’ll at least want a recipe for being able to bootstrap and teardown a Jasper application in Storyteller test harnesses. At a minimum, I’d like to expose a bit of diagnostics on the service bus activity during a Storyteller specification run like we did with FubuMVC in the Storyteller specification results HTML.

JasperHttp

We’re embracing ASP.net Core MVC at work, so this might just be a side project for fun down the road. The goal here is just to provide a mechanism for writing micro-services that expose HTTP endpoints. The I think the potential benefits over MVC are:

  • Less ceremony in writing HTTP endpoints (fewer attributes, no required base classes, no marker interfaces, no fluent interfaces)
  • The runtime model will be much leaner. We think that we can make Jasper about as efficient as writing purely explicit, bespoke code directly on top of ASP.Net Core
  • Easier testability

A couple folks have asked me about the timing on this one, but I think mid-summer is the earliest I’d be able to do anything about it.

JasperScheduler

If necessary, we’ll have another “Feature” library that extends JasperBus with the ability to schedule user supplied jobs. The intention this time around is to just use Quartz as the actual scheduler.

JasperQueues

This is a giant TBD

IoC Usage Plans

Right now, it’s going to be StructureMap 4.4+ only. While this will drive some folks away, it makes the tool much easier to build. Besides, Jasper is already using some StructureMap functionality for its own configuration. I think that we’re only positioning Jasper for greenfield projects (and migration from FubuMVC) anyway.

Regardless, the IoC usage in Jasper is going to be simplistic compared to what we did in FubuMVC and certainly less entailed than the IoC abstractions in ASP.net MVC Core. We theorize that this should make it possible to slip in the IoC container of your choice later.