Marten 7.0 is Released!

Marten 7.0 is released to the wild as of right now! Before getting into the highlights of what’s improved in this release, let’s go right to thanking some of the folks who made big contributions to this release either through code, testing, or feedback:

  • Oskar Dudycz and Babu Annamalai for being part of the core Marten team for most of its life
  • JT for all his feedback on the event sourcing feature set and being an early tester for us on the new LINQ support
  • Anne Erdtsieck for a slew of contributions both to Marten and the related Wolverine integration
  • Ben Edwards for advising us on event sourcing changes
  • Günther Foidl for making several suggestions on Marten’s execution pipeline, Npgsql usage, and for reviewing several very details pull requests
  • Mateusz Nowak for adding health checks to our asynchronous projection daemon
  • Zyrrio for sponsoring Marten!
  • Vedran Zakanj for sponsoring Marten and also contributing ideas around schema management
  • And a huge thanks to Lucas Wyland for specifically sponsoring the improved LINQ provider work with an equally huge apology from me on how long that took to finish

And to many more community members who helped improve Marten throughout this very long release cycle.

Highlights

This was a huge release, if not nearly as disruptive as Marten 4 was several years ago. I do not anticipate a lot of issues for users upgrading from Marten 6 to Marten 7, but see the migration guide for more details.

The highlights of Marten 7 are:

  • The LINQ query support was given a large overhaul that both expanded its supported use cases and led to significantly improved performance of many common sub collection queries — which has been a large complaint and request for improvement from the Marten community for several years
  • A “Partial” document update capability using native PostgreSQL functionality with no JavaScript in sight! That’s been a long requested capability.
  • The very basic database execution pipeline underneath Marten was largely rewritten to be far more parsimonious with how it uses database connections and to take advantage of more efficient Npgsql usage. We think these changes will make Marten both more efficient overall (these changes reduced the number of object allocations by quite a bit) and help system health through using fewer database connections
  • We introduced Polly for resiliency to transient errors like network hiccups or a temporarily overloaded database and actually made Marten able to properly execute retries of database writes and database reads
  • The “async daemon” subsystem was somewhat rewritten with substantial improvements for application scalability. The asynchronous projection support also has an all new scheme for resiliency that we think will be a big improvement for our users
  • An option to utilize Marten’s recommended FetchForWriting() API for “write model” aggregation with asynchronous projections. This may sound like a lot of mumbo jumbo, but it’s vital because this enables the next bullet point
  • The ability to do zero downtime deployments of some projection changes as well as to do blue/green deployments of revisioned projections. Much more on this later this week.
  • A new alternative for “revisioned” documents with a numeric version as an alternative to Marten’s existing GUID based versioning scheme for optimistic concurrency
  • We’ll see how big of a deal this turns out to be, but Marten 7 enables the usage of Project Aspire with Marten
  • Improved support for dynamically adding new tenant databases within Marten’s multi-tenancy support

As time permits, I will be writing deep dive blog posts on each of the individual bullet points above over the next couple weeks — partially as a way to force the completion of some not perfectly updated documentation!

You can Place a Technical Bet on Marten

There’s frequently an understandable hesitation on the part of software shops to take a bet on an open source tool as a critical piece of their technical infrastructure — and that’s sometimes worse in the .NET ecosystem where OSS adoption isn’t as widespread. All that aside, I’m here to tell you that you can feel safe making a large technical bet on Marten because:

  • Marten is already a very mature project that has been in production usage since its 1.0 release in 2016
  • While Marten doesn’t have every single issue around production support, deployments, and schema management fixed yet, we’ve got a detailed roadmap to shore up any remaining weaknesses of the tool and we’re in this for the long haul!
  • PostgreSQL itself is a very successful open source project that continuously innovates and provides a very solid technical foundation for Marten itself
  • Marten has a vibrant user community as you can see from the community involvement with GitHub and our Discord chat rooms.
  • We’ve invested a lot of time into refining Marten’s usability over the years and we think that attention to detail shines through
  • JasperFx Software offers support contracts and consulting work for Marten users
  • In conjunction with Wolverine’s integration with Marten, the full “Critter Stack” provides a very efficient and usable stack for Event Driven Architecture using Event Sourcing and a CQRS architecture
  • While Marten 7.0 made some significant improvements for scalability, the forthcoming “Critter Stack Pro” commercial add on tooling will take Marten to much larger data sets and transactional throughput
  • Because Marten does target .NET, it’s worth pointing out that at this point, Microsoft has no technical offerings for Event Sourcing and that will absolutely contribute to Marten’s viability

What’s Next and Summary

A lot of big, important, long requested, long planned features and improvements did not make the cut for V7. I blogged last week about the current roadmap for the entire Critter Stack. Moreover, some open bugs didn’t make it into 7.0 as well. And let’s be honest, there’s going to be a slew of bug reports streaming in this week when folks try out new 7.0 features and encounter usage permutations we didn’t anticipate. I’ve finally learned my lesson and made this release after having gotten some rest to be ready for whatever the issues turn out to be in the morning.

Wolverine 2.0 will also follow shortly, but the roadmap for that is pretty well just upgrading to Marten 7, dumping .NET 6, and fixing some low hanging fruit issues and requests before a release in the next couple days.

We’ll jump on whatever those Marten 7 issues turn out to be and all the questions about “what about *my* use case I don’t see on your list!” starting tomorrow, but for right now, this was a huge release filled with all kinds of substantial improvements that for the first time included significant client sponsored requests and please don’t steal my sunshine!

Talking with Isaac Levin on Coffee & Open Source

Isaac Levin was kind enough to have me on his Coffee & Open Source show to talk about a variety of topics around technology and my involvement with OSS work.

I need to update my profile here and there, that picture was taken on my late grandparents farm around Christmas of 2010 outside the titular Jasper, MO

I’d say that my time in OSS has long been valuable in terms of increased technical skillset and occasionally through opportunities that arose because of my OSS tools. It’s just now though that I’m finally living out my longstanding dream to make my “Critter Stack” OSS work (Marten & Wolverine) be my actual job as part of JasperFx Software.

Just to call a few highlights and to add to our conversation after having some time to think about things:

  • I made a double edged bit of advice at the end to “take your shot” when you have a technical idea that could become your job, but followed by an exhortation to stop working on something that isn’t bringing you joy or opportunities.
  • Unfortunately, failure is an awesomely effective teacher — if you let it be. I feel like the Critter Stack tools are succeeding right now, and plenty of that is due to some harsh lessons learned from my earlier failures in OSS.
  • OSS projects can succeed with a mix of having a conceptual idea or approach that appeals to enough folks, a dedicated core team of contributors like Oskar and Babu, and an enthusiastic and patient community that helps with suggestions, bug reports, and contributions. I called out Wolverine especially as a tool whose usability has largely been driven by the feedback of several early adopters. Moreover, one of the hard lessons learned from my earlier failure with FubuMVC is how important it is to get enough user feedback to sand off rough edges with a tool’s usability or documentation.
  • I personally find it very gratifying to be working on my projects, carrying out my vision, and generally having my hand on the steering wheel of Marten and Wolverine. I’m also enjoying the hands on consulting engagements I’m doing with the current JasperFx clients and making a positive difference for them. The obvious takeaway for me — and probably for a great number of you out there as well — is that I am much happier when I feel like I have significant ownership over the work and that my contributions are respected and valued by the customer, management, product owner, or colleagues. I’ve been consistently miserable in jobs or roles where I didn’t have either of those two things.

A Swag at the Critter Stack Road Map for Early 2024

From some notes that Oskar, Babu, and I banged out this past week, so keep your expectations for the quality of prose here! Notes in bold are my updates since this original document was banged out last weekend.

Marten 7.0

Try to release Marten 7.0 no later than early next week. This is admittedly based on JasperFx client deliverables.

  1. In flight work with async daemon and dynamic tenant databases. I think at this point it’s just finishing off that big PR. Done.
  2. Blue/green & zero downtime deployment. Ongoing work that just needs more testing at this point. This includes the projection version stuff. Actually all working locally, but my development branch is rebased on the daemon stuff, so I’d like that to go in first. Done.
  3. Update docs — Work in progress!
  4. Maybe try Project Aspire one more time? I think this could float to 7.1 as well. Likely to float to 7.1, but let’s see how this next week goes
  5. Triage bugs and minor issues

“Critter Stack Pro” work that might force breaking changes to Marten APIs. At *least* do some spikes:

  • Distributed async projections. This one’s the big one. Proceeding well, did cause a few changes to Marten so far
  • Projection Snapshots – I’d really like to see this mostly land in Critter Stack Pro. Probably not happening until 2nd quarter 2024
  • First class subscriptions from the event store to Wolverine transports – might be in Wolverine 2.0 proper. Dunno. Not sure yet
  • Async projection optimizations – Probably not happening until 2nd quarter 2024
    • 2nd level caching for aggregates
    • Rebuild single stream projections stream by stream
    • Allow for selective identity map usage of reference types. 
    • Batched data lookups – so you can keep projections from doing chatty data access
    • Allow grouping logic to express optimization hints like “no data access required” or “requires aggregate state”. That could be used to optimize projection rebuilds

Wolverine 2.0

  • Discovery and activation of new tenant databases at runtime (client deliverable). Done.
  • Update to Marten 7
  • Project Aspire? Wolverine 2.1? This is a little more involved, so I’m not sure yet when this lands. Probably in Wolverine 2.1.

Marten 7.1

  1. Open Telemetry Support – Sean Farrow is working on this. I don’t think it’s going to be a breaking change, so could float to 7.1. Very Basic
  2. Sharding the event store tables – I’d love to do this sooner, and would love to stretch this in. I’m saying that we would tackle the is archived / not archived sharding in a first pass, then come back w/ fancier sharding possibilities later. This would have a potentially huge positive implication for Marten event store scalability.
  3. The ability to “emit” new events in the async daemon during the course of processing asynchronous projections. I think this is going to take some spikes and analysis, so we gotta commit to this ASAP if it’s going into 7.0. This is falling to Marten 7.1
  4. Strong-typed identifiers – it’s a ton of work I really don’t want to take on in a rush (Jeremy)
  5. First class subscriptions. Hot, cold, replay, whatever. I just want a little more time and space. Does this require any breaking changes in the daemon we might want to deal with right now though? Very likely dropping to Marten 7.1
  6. Custom event type naming strategy – it’s a breaking change to the API I think. I don’t think it’s huge though – little pluggable strategy. Can be additive.
  7. Optimize inline projections in FetchForWriting()? Idea here is to force aggregates that are calculated Inline (or Async maybe) that are queried in FetchForWriting() be forced to use the identity map for just that document type. That does a lot to optimize the typical “aggregate handler workflow” by avoiding the current double fetching of the document when you are using lightweight sessions. Strong candidate to drop down to 7.1

Marten 7.Later

  • Downcasters – I vote to put this into Critter Stack Pro all the way

Marten 8.0???

  • More advanced Event Store partitioning

Wolverine 2.1

  • Likely a focus on the Wolverine.HTTP backlog
  • Options for strict ordering requirements of event or message processing

Sneak Peek at “Critter Stack Pro” for Big Time Event Store Scalability

Hey, did you know that JasperFx Software is ready for 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.

In the continuing saga of trying to build a sustainable business model around Marten and Wolverine (the “Critter Stack”), JasperFx Software is quietly building a new set of tools code named “Critter Stack Pro” as a commercially licensed add on to the MIT-licensed OSS core tools.

While there’s some very serious progress on a potential management user interface tool for Marten & Wolverine features underway, the very first usable piece will be a new library for scaling Marten’s asynchronous projection model by much more efficiently distributing work across a clustered application than Marten by itself can today.

In the first wave of work, we’re aiming for this feature set:

  • When using a single Marten database, the execution of asynchronous projections will be distributed evenly across the application cluster
  • When using multiple Marten databases for multi-tenancy, the execution of asynchronous projections will be distributed by database and evenly across the application cluster
  • In blue/green deployments, “Critter Stack Pro” will be able to ensure that all known versions of each projection and database are executing in a suitable “blue” or “green” node within the application cluster
  • When using multiple Marten databases for multi-tenancy and also using the new dynamic tenant capability in Marten 7.0, “Critter Stack Pro” will discover the new tenant databases at runtime and redistribute projection work across the application cluster
  • “First class subscriptions” of Marten events with strict ordering through any of Wolverine’s supported messaging transports (locally, Rabbit MQ, Kafka, Azure Service Bus, AWS SQS, soon to be more!).

We’re certainly open to more suggestions from long term and potential users about what other features would make “Critter Stack Pro” a must have tool for your production environment. Trigger projection projection rebuilds on demand? Apply a new subscription? Pause a subscription? Force “Critter Stack Pro” to redistribute projections across the cluster? Smarter distribution algorithms based on predicted load? Adaptive distribution based on throughput?

And do know that we’re already working up a potential user interface for visualizing and monitoring Marten and Wolverine’s behavior at runtime.

This new product (knock on wood) is going to be delivered to a JasperFx customer within the next week or two for integration into their systems using Marten 7.0 and Wolverine 2.0 (also not coincidentally forthcoming at the end of the next week). I’m not going to commit to when this will be generally available, but I’d sure hope it’s sometime in the 2nd quarter this year.

Answering Some Concerns about Wolverine

Nick Chapsas just released a video about Wolverine with his introduction and take on the framework. Not to take anything away from the video that was mostly positive, but I thought there were quite a few misconceptions about Wolverine evident in the comments and some complaints I would like to address so I can stop fussing about this and work on much more important things.

First off, what is Wolverine? Wolverine is a full blown application framework and definitely not merely a “library,” so maybe consider that when you are judging the merits of its opinions or not. More specifically, Wolverine is a framework built around the idea of message processing where “messages” could be coming from inline invocation like MediatR or local in process queues or external message brokers through asynchronous messaging ala the much older MassTransit or NServiceBus frameworks. In addition, Wolverine’s basic runtime pipeline has also been adapted into an alternative HTTP endpoint framework that could be used in place of or as a complement to MVC Core or Minimal API.

I should also point out that Wolverine was largely rescued off the scrap heap and completely rebooted specifically to work in conjunction with Marten as a full blow event driven architecture stack. This is what we mean when we say “Critter Stack.”

In its usage, Wolverine varies quite a bit from the older messaging and mediator tools out there like NServiceBus, MassTransit, MediatR, Rebus, or Brighter.

Basically all of these existing tools one way or another force you to constrain your code within some kind of “IHandler of T” abstraction something like this:

public interface IHandler<T>
{
    Task HandleAsync(T message, MessageContext context, CancellationToken cancellationToken);
}

By and large, these frameworks assume that you will be using an IoC container to fill any dependencies of the actual message handler classes through constructor injection. Part of the video I linked to was the idea that Wolverine was very opinionated, so let’s just get to that and see how Wolverine very much differs from all the older “IHandler of T” frameworks out there.

Wolverine’s guiding philosophies are to:

  • Reduce code ceremony and minimize coupling between application code and the surrounding framework. As much as possible — and it’s an imperfect world so the word is “minimize” and not “eliminate” — Wolverine attempts to minimize the amount of code cruft from required inheritance, marker interfaces, and attribute usage within your application code. Wolverine’s value proposition is that lower ceremony code leads to easier to read code that offsets any disadvantages that might arise from using conventional approaches
  • Promote testability — both by helping developers structure code in such a way that they can keep infrastructure concerns out of business logic for easy unit testing and to facilitate effective automated integration testing as well. I’ll throw this stake in the ground right now, Wolverine does much more to promote testability than any other comparable framework that I’m aware of, and I don’t mean just .NET frameworks either (Proverbs 16:18 might be relevant here, but shhh).
  • “It should just work” — meaning that as much as possible, Wolverine should try to set up infrastructural state (database schemas, message broker configuration, etc.) that your application depends on for an efficient developer experience
  • Provide effective diagnostics for any “magic” in the framework. See Unraveling the Magic in Wolverine to see what I mean.
  • Bake in logging, auditing, and observability so that developers don’t have to think about it. This is partially driven by the desire for low code ceremony because nothing is more repetitive in systems than copy/paste log statements every which way
  • Be as performant as possible. Wolverine is descended and influenced by an earlier failed OSS project called FubuMVC that strived for very low code ceremony and testability, but flunked on performance and how it handled “magic” conventions. Let’s just say that failure is a harsh but effective teacher. In particular, Wolverine tries really damn hard to reduce the number of object allocations and dictionary lookups at runtime as those are usually the main culprits of poor performance in application frameworks. I fully believe that before everything is said and done, that Wolverine will be able to beat the other tools in this space because of its unique runtime architecture.

A Wolverine message handler might look something like this from one of our samples in the docs that happens to use EF Core for persistence:

public static class CreateItemCommandHandler
{
    public static ItemCreated Handle(
        // This would be the message
        CreateItemCommand command,

        // Any other arguments are assumed
        // to be service dependencies
        ItemsDbContext db)
    {
        // Create a new Item entity
        var item = new Item
        {
            Name = command.Name
        };

        // Add the item to the current
        // DbContext unit of work
        db.Items.Add(item);

        // This event being returned
        // by the handler will be automatically sent
        // out as a "cascading" message
        return new ItemCreated
        {
            Id = item.Id
        };
    }
}

There’s a couple things I’d ask you to notice right off the bat that will probably help inform you if you’d like Wolverine’s approach or not:

There’s no required IHandler<T> type interface. Nor do we require any kind of IMessage/IEvent/ICommand interface on the message type itself

The method signatures of Wolverine message handlers are pretty flexible. Wolverine can do “method injection” like .NET developers are used to now in Minimal API or the very latest MVC Core where services from the IoC container are pushed into the handler methods via method parameters (Wolverine will happily do constructor injection just like you would in other frameworks as well). Moreover, Wolverine can even do different things with the handler responses like “know” that it’s a separate message to publish via Wolverine or a “side effect” that should be executed inline. Heck, the message handlers can even be static classes or methods to micro-optimize your code to be as low allocation as possible.

Wolverine is not doing any kind of runtime Reflection against these handler methods, because as a commenter pointed out, this would indeed be very slow. Instead, Wolverine is generating and compiling C# code at runtime that wraps around your method. Going farther, Wolverine will use your application’s DI configuration code and try to generate code that completely takes the place of your DI container at runtime. Some folks complain that Wolverine forces you to use Lamar as the DI container for your application, but doing so enabled Wolverine to do the codegen the way that it is. Nick pushed back on that by asking what if the built in DI container becomes much faster than Lamar (it’s the other way around btw)? I responded by pointing out that the fasted DI container is “no DI container” like Wolverine is able to do at runtime.

The message handlers are found by default through naming conventions. But if you hate that, no worries, there are options to use much more explicit approaches. Out of the box, Wolverine also supports discovery using marker interfaces or attributes. I don’t personally like that because I think it “junks up the code”, but if you do, you can have it your way.

The handler code above was written with the assumption that it’s using automatic transactional middleware around it all that handles the asynchronous code invocation, but if you prefer explicit code, Wolverine happily lets you eschew any of the conventional magic and write explicit code where you would be completely in charge of all the EF Core usage. The importance of being able to immediately bypass any conventions and drop into explicit code as needed was an important takeaway from my earlier FubuMVC failure.

    Various Objections to Wolverine

    • It’s opinionated, and I don’t agree with all of Wolverine’s opinions. This one is perfectly valid. If you don’t agree with the idiomatic approach of a software development tool, you’re far better off to just pick something else instead of fighting with the tool and trying to use it differently than its idiomatic usage. That goes for every tool, not just Wolverine. If you’d be unhappy using Wolverine and likely to gripe about it online, I’d much rather you go use MassTransit.
    • Runtime reflection usage? As I said earlier, Wolverine does not use reflection at runtime to interact with the message handlers or HTTP endpoint methods
    • Lamar is required as your IoC tool. I get the objection to that, and other people have griped about that from time to time. I’d say that the integration with Lamar enables some of the very important “special sauce” that makes Wolverine different. I will also say that at some point in the future we’ll investigate being able to at least utilize Wolverine with the built in .NET DI container instead
    • Oakton is a hard dependency, and why is Wolverine mandating console usage? Yeah, I get that objection, but I think that’s very unlikely to ever really matter much. You don’t have to use Oakton even though it’s there, but Wolverine (and Marten) both heavily utilize Oakton for command line diagnostics that can do a lot for infrastructure management, environment checks, code generation, database migrations, and important diagnostics that help users unravel and understand Wolverine’s “magic”. We could have made that all be separate adapter package or add ons, but from painful experience, I know that the complexity of usage and development of something like Wolverine goes up quite a bit with the number of satellite packages you use and require — and that’s already an issue even so with Wolverine. I did foresee the Lamar & Oakton objections, but consciously decided that Wolverine development and adoption would be easier — especially early on — by just bundling things together. I’d be willing to reconsider this in later versions, but it’s just not up there in ye olde priority list
    • There are “TODO” comments scattered in the documentation website! There’s a lot of documentation up right now, and also quite a few samples. That work is never, ever done and we’ll be improving those docs as we go. The one thing I can tell you definitively about technical documentation websites is that it’s never good enough for everyone.

    Side Effects vs Cascading Messages in Wolverine

    Hey, did you know that JasperFx Software is ready for 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.

    Wolverine has a pair of features called cascading messages and side effects that allow users to designate “work” that happens after your main message handler or HTTP endpoint method. In our Discord room this week, there was a little bit of user confusion over what the difference was and when you should use one or the other. To that end, let’s do a little dive into what both of these features are (both are unique to Wolverine and don’t have analogues to the best of my knowledge in any other messaging or command processing framework in the .NET space).

    First, let’s take a look at “side effects.” Here’s the simple example of a custom “side effect” from the Wolverine documentation to write string data to a file on the file system:

    public class WriteFile : ISideEffect
    {
        public string Path { get; }
        public string Contents { get; }
    
        public WriteFile(string path, string contents)
        {
            Path = path;
            Contents = contents;
        }
    
        // Wolverine will call this method. 
        public Task ExecuteAsync(PathSettings settings)
        {
            if (!Directory.Exists(settings.Directory))
            {
                Directory.CreateDirectory(settings.Directory);
            }
            
            return File.WriteAllTextAsync(Path, Contents);
        }
    }
    

    And a message handler that uses this custom side effect:

    public class RecordTextHandler
    {
        public WriteFile Handle(RecordText command)
        {
            return new WriteFile(command.Id + ".txt", command.Text);
        }
    }
    

    A Wolverine “side effect” really just designates some work that should happen inline with your message or HTTP request handling, so we could eschew the “side effect” and rewrite our message handler as:

        public Task Handle(RecordText command, PathSettings settings)
        {
            if (!Directory.Exists(settings.Directory))
            {
                Directory.CreateDirectory(settings.Directory);
            }
            
            return File.WriteAllTextAsync(command.Id + ".txt", command.Text);
        }
    

    The value of the “side effect” usage within Wolverine is to allow you to make a message or HTTP endpoint method be responsible for deciding what to do, without coupling that method and its logic to some kind of pesky infrastructure like the file system that becomes a pain to deal with in unit tests. The “side effect” object returned from a message handler or HTTP endpoint is running inline within the same transaction (if there is one) and retry loop for the message itself.

    On the other hand, a cascading message is really just sending a subsequent message after the successful completion of the original message. Here’s an example from the “Building a Critter Stack Application” blog series:

        [WolverinePost("/api/incidents/categorise"), AggregateHandler]
        // Any object in the OutgoingMessages collection will
        // be treated as a "cascading message" to be published by
        // Wolverine after the original CategoriseIncident command
        // is successfully completed
        public static (Events, OutgoingMessages) Post(
            CategoriseIncident command, 
            IncidentDetails existing, 
            User user)
        {
            var events = new Events();
            var messages = new OutgoingMessages();
            
            if (existing.Category != command.Category)
            {
                events += new IncidentCategorised
                {
                    Category = command.Category,
                    UserId = user.Id
                };
    
                // Send a command message to try to assign the priority
                messages.Add(new TryAssignPriority
                {
                    IncidentId = existing.Id
                });
            }
    
            return (events, messages);
        }
    }
    

    In the example above, the TryAssignPriority message will be published by Wolverine to whatever subscribes to that message type (local queues, external transports, nowhere because nothing actually cares?). The “cascading messages” are really the equivalent to calling IMessageBus.PublishAsync() on each cascaded message. It’s important to note that cascaded messages are not executed inline with your original message. Instead, they are only published after the original message is completely handled, and will run in completely different contexts, retry loops, and database transactions.

    To sum up, you would:

    1. Use a “side effect” to select actions that need to happen within the current message context as part of an atomic transaction and as something that should succeed or fail (and be retried) along with the message handler itself and any other middleware or post processors for that message type. In other words, “side effects” are for actions that should absolutely happen right there and now!
    2. Use a “cascaded message” for a subsequent action that should happen after the current message, should be executed within a separate transaction, or could be retried in its own retry loop after the original message handling has succeeded.

    I’d urge users to consider the proper transaction boundaries and retry boundaries to decide which approach to use. And remember that in both cases, there is value in trying to use pure functions for any kind of business or workflow logic — and both side effects and cascaded messages help you do exactly that for easily unit testable code.

    Ongoing Scalability Improvements for Marten 7

    Hey, did you know that JasperFx Software is ready for 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.

    I checked this morning, and Marten’s original 1.0 release was in September of 2016. Since then we as a community have been able to knock down several big obstacles to user adoption, but one pernicious concern of new users was the ability to scale the asynchronous projection support to very large loads as Marten today only supports a “hot/cold” model where all projections run in the same active process.

    Two developments are going to finally change that in the next couple weeks. First off, the next Marten 7 beta is going to have a huge chunk of work on Marten’s “async daemon” process that potentially distributes work across multiple nodes at runtime.

    By (implied) request:

    In the new Marten 7 model:

    • If you are targeting a single database, Marten will do its potential ownership of each projection independently. We’re doing this by using PostgreSQL advisory locks for the determination of ownership on a projection by projection basis. At runtime, we’re using a little bit of randomness so that if you happen to start up multiple running application nodes at the same time, the different nodes will start checking for that ownership at random times and do so with a random order of the various projections. It’s not fool proof by any means, but this will allow Marten to potentially spread out the projections to different running application instances.
    • If you are using multi-tenancy through separate databases, Marten’s async daemon will similarly do an ownership check by database, and keep all the projections for a single database running on the same node. This is done with the theory that this should potentially reduce the number of database connections used overall by your system. As in the previous bullet for a single tenant, there’s some randomness introduced so each application instance doesn’t try to get ownership of the same databases at the same time and potentially cause dead lock situations. Likewise, Marten is randomizing the order in which it attempts to check the ownership of different databases so there’s a chance this strategy will distribute work across multiple nodes.

    There’s some other improvements so far (with hopefully much more to follow) that we hope will increase the throughput of asynchronous projections, especially for projection rebuilds.

    I should also mention that a JasperFx Software client has engaged us to improve Marten & Wolverine‘s support for dynamic utilization of per tenant databases where both Marten & Wolverine are able to discover new tenant databases at runtime and activate all necessary support agents for the new databases. That dynamic tenant work in part led to the async projection work I described above.

    Let’s go even farther…

    I’ll personally be very heads down this week on some very long planned work (sponsored by a JasperFx Software client!!!) for a “Critter Stack Pro” tool set to extend Marten’s event store to much larger data sets and throughput. This will be the first of a suite of commercial add on tools to the “Critter Stack”, with the initial emphasis being:

    • The ability to more effectively distribute asynchronous projection work across the running instances of the application using a software-based “agent distribution” already built into Wolverine. We’ll have some simple rules for how projections are distributed upfront, but I’m hoping to evolve into adaptive rules later that can adjust the distribution based on measured load and performance metrics
    • Zero-downtime deployments of Marten projection changes
    • Blue/green deployments of revisioned Marten projections and projected aggregates, meaning that you will be able to deploy a new version of a Marten projection in some running instances of a server applications while the older version is still functional in other running instances

    I won’t do anything silly like put a timeframe around this, but the “Critter Stack Pro” will also include a user interface management console to watch and control the projection functionality.

    It’s Critter Stack “Release on Friday” Party!

    Hey, did you know that JasperFx Software is ready for formal support plans for Marten and Wolverine? Not only are we trying to make 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 any other .NET server side tooling.

    A lot of pull requests and bug fixes just happened to land today for both Marten and Wolverine. In order, we’ve got:

    Marten 7.0.0 Beta 5

    Marten 7.0.0 Beta 5 is actually quite a big release and a major step forward on the road to the final V7 release. Besides some bug fixes, I think the big highlights are:

    • Marten finally gets the long awaited “Partial Update” model that only depends on native PosgreSQL features! Huge addition from Babu. If you’re coming to Marten from MongoDb, or only would if Marten had the ability to modify documents without first having to load the whole thing, well now you can! No PLv8 extension necessary!
    • We pushed through a new low level execution model that’s more parsimonious about how long database connections are kept open that should help applications using Marten scale to more concurrent transactions. This should also help folks using Marten in conjunction with Hot Chocolate as now IQuerySession could be used in multiple threads in parallel.
    • Marten now uses Polly internally for retries on transient errors, and the “retry” functionality actually works now (it didn’t actually do anything useful before, as I shamefully refuse to make eye contact with you).
    • Several fixes around full text indexes that were blocking some folks

    Wolverine 1.16.0

    Wolverine 1.16.0 came out today with a couple additions and fixes related to MQTT or Rabbit MQ message publishing to topics. As an example, here’s some new functionality with Rabbit MQ message publishing:

    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:

    using var host = await Host.CreateDefaultBuilder()
        .UseWolverine((context, 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();
        })
        .StartAsync();
    

    Wolverine 2.0 Alpha 1

    Knock on wood, if the GitHub Action & Nuget gods all agree, there will be a Wolverine 2.0 alpha 1 set of Nugets available that’s just Wolverine 1.16, but targeting the very latest Marten 7 betas as somebody asks me just about every single day when that’s going to be ready.

    Enjoy! And don’t tell me about any problems with these releases until Monday!

    Summary

    I had a very off week as I struggled with a cold, a busy personal life, and way more Zoom meetings than I normally have. All the same, getting to spit out these three releases today makes me feel like Bill Murray here:

    And again, new bug reports can wait for Monday!

    Building a Critter Stack Application: Resiliency

    Hey, did you know that JasperFx Software is ready for formal support plans for Marten and Wolverine? Not only are we trying to make 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 any other .NET server side tooling.

    Let’s build a small web service application using the whole “Critter Stack” and their friends, one small step at a time. For right now, the “finished” code is at CritterStackHelpDesk on GitHub.

    The posts in this series are:

    1. Event Storming
    2. Marten as Event Store
    3. Marten Projections
    4. Integrating Marten into Our Application
    5. Wolverine as Mediator
    6. Web Service Query Endpoints with Marten
    7. Dealing with Concurrency
    8. Wolverine’s Aggregate Handler Workflow FTW!
    9. Command Line Diagnostics with Oakton
    10. Integration Testing Harness
    11. Marten as Document Database
    12. Asynchronous Processing with Wolverine
    13. Durable Outbox Messaging and Why You Care!
    14. Wolverine HTTP Endpoints
    15. Easy Unit Testing with Pure Functions
    16. Vertical Slice Architecture
    17. Messaging with Rabbit MQ
    18. The “Stateful Resource” Model
    19. Resiliency (this post)

    Sometimes, things go wrong in production. For any number of reasons. But all the same, we want to:

    • Protect the integrity of our system state
    • Not lose any ongoing work
    • Try not to require manual interventions to put things right in the system
    • Keep the system from going down even when something is overloaded

    Fortunately, Wolverine comes with quite a few facilities for adding adaptive and selective resiliency to our systems — especially when doing asynchronous processing.

    First off, we’re using Marten in our incident tracking, help desk system to read and persist data to a PostgreSQL database. When handling messages, Wolverine could easily encounter transient (read: random and not necessarily systematic) exceptions related to network hiccups or timeout errors if the database happens to be too busy at that very time. Let’s tell Wolverine to apply a little exponential backoff (close enough for government work) and retry a command that hits one of these transient database errors a limited number of times like this within the call to UseWolverine() within our Program file:

        // Let's build in some durability for transient errors
        opts.OnException<NpgsqlException>().Or<MartenCommandException>()
            .RetryWithCooldown(50.Milliseconds(), 100.Milliseconds(), 250.Milliseconds());
    
    

    The retries may happily catch the system at a later time when it’s not as busy, so the transient error doesn’t reoccur and the message can succeed. If we get successive failures, we wait longer before retries. This retry policy effectively throttles a Wolverine system and may give a distressed subsystem within your architecture (in this case the PostgreSQL database) a chance to recover.

    Other times you may have a handler encounter an exception that tells us the message in question is invalid somehow, and could never be handled. There’s absolutely no reason to retry that message, so instead, let’s tell Wolverine to instead discard that message immediately (and not even bother to move it to a dead letter queue):

        // Log the bad message sure, but otherwise throw away this message because
        // it can never be processed
        opts.OnException<InvalidInputThatCouldNeverBeProcessedException>()
            .Discard();
    

    I’ve done a few integration projects now where some kind of downstream web service was prone to being completely down. Let’s pretend that we’re only calling that web service through a message handler (my preference whenever possible for exactly this failure scenario) and can tell from an exception that the web service is absolutely unavailable and no other messages could possibly go through until that service is fixed.

    Wolverine can do that as well, like so:

        // Shut down the listener for whatever queue experienced this exception
        // for 5 minutes, and put the message back on the queue
        opts.OnException<MakeBelieveSubsystemIsDownException>()
            .PauseThenRequeue(5.Minutes());
    

    And finally, Wolverine also has a circuit breaker functionality to shut down processing on a queue if there are too many errors in a certain time. This feature certainly applies to messages coming in from external messages from Rabbit MQ or Azure Service Bus or AWS SQS, but can also apply to database backed local queues. For the help desk system, I’m going to add a circuit breaker to the local queue for processing the TryAssignPriority command to pause all local processing on the current node if a certain threshold of message processing is failing:

        opts.LocalQueueFor<TryAssignPriority>()
            // By default, local queues allow for parallel processing with a maximum
            // parallel count equal to the number of processors on the executing
            // machine, but you can override the queue to be sequential and single file
            .Sequential()
    
            // Or add more to the maximum parallel count!
            .MaximumParallelMessages(10)
    
            // Pause processing on this local queue for 1 minute if there's
            // more than 20% failures for a period of 2 minutes
            .CircuitBreaker(cb =>
            {
                cb.PauseTime = 1.Minutes();
                cb.SamplingPeriod = 2.Minutes();
                cb.FailurePercentageThreshold = 20;
                
                // Definitely worry about this type of exception
                cb.Include<TimeoutException>();
                
                // Don't worry about this type of exception
                cb.Exclude<InvalidInputThatCouldNeverBeProcessedException>();
            });
    

    And don’t worry, Wolverine won’t lose any additional messages published to that queue. They’ll just sit in the database until the current node picks back up on this local queue or another running node is able to steal the work from the database and continue.

    Summary and What’s Next

    I only gave some highlights here, but Wolverine has some more capabilities for error handling. I think these policies are probably something you adapt over time as you learn more about how your system and its dependencies behave. Throwing more descriptive exceptions from your own code is definitely beneficial as well for these kinds of error handling policies.

    I’m almost done with this series. I think the next post or two — and it won’t come until next week — will be all about logging, auditing, metrics, and Open Telemetry integration.

    Building a Critter Stack Application: The “Stateful Resource” Model

    Hey, did you know that JasperFx Software is ready for formal support plans for Marten and Wolverine? Not only are we trying to make 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 any other .NET server side tooling.

    Let’s build a small web service application using the whole “Critter Stack” and their friends, one small step at a time. For right now, the “finished” code is at CritterStackHelpDesk on GitHub.

    The posts in this series are:

    1. Event Storming
    2. Marten as Event Store
    3. Marten Projections
    4. Integrating Marten into Our Application
    5. Wolverine as Mediator
    6. Web Service Query Endpoints with Marten
    7. Dealing with Concurrency
    8. Wolverine’s Aggregate Handler Workflow FTW!
    9. Command Line Diagnostics with Oakton
    10. Integration Testing Harness
    11. Marten as Document Database
    12. Asynchronous Processing with Wolverine
    13. Durable Outbox Messaging and Why You Care!
    14. Wolverine HTTP Endpoints
    15. Easy Unit Testing with Pure Functions
    16. Vertical Slice Architecture
    17. Messaging with Rabbit MQ
    18. The “Stateful Resource” Model (this post)
    19. Resiliency

    I’ve personally spent quite a bit of time helping teams and organizations deal with older, legacy codebases where it might easily take a couple days of working painstakingly through the instructions in a large Wiki page of some sort in order to make their codebase work on a local development environment. That’s indicative of a high friction environment, and definitely not what we’d ideally like to have for our own teams.

    Thinking about the external dependencies of our incident tracking, help desk api we’ve utilized:

    1. Marten for persistence, which requires our system to need PostgreSQL database schema objects
    2. Wolverine’s PostgreSQL-backed transactional outbox support, which also requires its own set of PostgreSQL database schema objects
    3. Rabbit MQ for asynchronous messaging, which requires queues, exchanges, and bindings to be set up in our message broker for the application to work

    That’s a bit of stuff that needs to be configured within the Rabbit MQ or PostgreSQL infrastructure around our service in order to run our integration tests or the application itself for local testing.

    Instead of the error prone, painstaking manual set up laboriously laid out in a Wiki page somewhere where you can’t remember where it is, let’s leverage the Critter Stack’s “Stateful Resource” model to quickly set our system up ready to run in development.

    Building on our existing application configuration, I’m going to add a couple more lines of code to our system’s Program file:

    // Depending on your DevOps setup and policies,
    // you may or may not actually want this enabled
    // in production installations, but some folks do
    if (builder.Environment.IsDevelopment())
    {
        // This will direct our application to set up
        // all known "stateful resources" at application bootstrapping
        // time
        builder.Services.AddResourceSetupOnStartup();
    }
    

    And that’s that. If you’re using the integration test harness like we did in an earlier post, or just starting up the application normally, the application will check for the existence of any of the following, and try to build out anything that’s missing from:

    • The known Marten document tables and all the database objects to support Marten’s event sourcing
    • The necessary tables and functions for Wolverine’s transactional inbox, outbox, and scheduled message tables (I’ll add a post later on those)
    • The known Rabbit MQ exchanges, queues, and bindings

    Your application will have to have administrative privileges over all the resources for any of this to work of course, but you would have that at development time at least.

    With this capability in place, the procedure for a new developer getting started with our codebase is to:

    1. Does a clean git clone of our codebase on to his local box
    2. Runs docker compose up to start up all the necessary infrastructure they need to run the system or the system’s integration tests locally
    3. Just run the integration tests or start the system and go!

    Easy-peasy.

    But wait, there’s more! Assuming you have Oakton set up as your command line like we did in an earlier post, you’ve got some command line tooling that can help as well.

    If you omit the call to builder.Services.AddResourceSetupOnStartup();, you could still go to the command line and use this command just once to set everything up:

    dotnet run -- resources setup
    

    To check on the status of any or all of the resources, you can use:

    dotnet run -- resources check
    

    which for the HelpDesk.API, gives you this:

    If you want to tear down all the existing data — and at least attempt to purge any Rabbit MQ queues of all messages — you can use:

    dotnet run -- resources clear
    

    There’s a few other options you can read about in the Oakton documentation for the Stateful Resource model, but for right now, type dotnet run -- help resources and you can see Oakton’s built in help for the resources command that runs down the supported usage:

    Summary and What’s Next

    The Critter Stack is trying really hard to create a productive, low friction development ecosystem for your projects. One of the ways it tries to make that happen is by being able to set up infrastructural dependencies automatically at runtime so a developer and just “clone n’ go” without the excruciating pain of the multi-page Wiki getting started instructions so painfully common in legacy codebases.

    This stateful resource model is also supported for Kafka transport (which is also local development friendly) and the cloud native Azure Service Bus transport and AWS SQS transport (Wolverine + AWS SQS does work with LocalStack just fine). In the cloud native cases, the credentials from the Wolverine application will have to have the necessary rights to create queues, topics, and subscriptions. In the case of the cloud native transports, there is an option to prefix all the names of the queues, topics, and subscriptions to still create an isolated environment per developer for a better local development story even when relying on cloud native technologies.

    I think I’ll add another post to this series where I switch the messaging to one of the cloud native approaches.

    As for what’s next in this increasingly long series, I think we still have logging, open telemetry and metrics, resiliency, and maybe a post on Wolverine’s middleware support. That list is somewhat driven by recency bias around questions I’ve been asked here or there about Wolverine.