Author Archives: jeremydmiller

Marten 2.10.0 and 3.0.0-alpha-2 are released.

The latest set of changes to Marten were just published as Marten 2.10.0 and Marten 3.0.0-alpha-2, with the only real difference being that the 3.0 alpha supports Npgsql 4. The complete list of changes is here. The latest docs have also been published. I counted 15 users total (not including me) in this release as either contributors or just folks who took the time to write up an actionable bug report (and don’t minimize the importance of that because it helps a ton). Thank you to all the Marten contributors and all the folks who answer questions in the Gitter room.

Do note that I quietly and unilaterally exercised my rights as the project’s benevolent dictator to finally remove Marten’s targeting for Netstandard1.* as it was annoying the crap out of me and I didn’t think many folks would care. As of 2.10.0, Marten targets net46 and netstandard2.0.

I hope that more serious work on the 3.0 release starts up again soon, but we’ll see.

Advertisements

OSS Plans for 2018 at the Halfway Point

This might be just navel gazing, but I do have some announcements in here too. 

I’ve made some remarks in the past year that I wanted to drastically scale back my OSS work after I finished the big things that are in flight. I think I’ve changed my mind to just finding a sustainable pace and continuing on. What I’ve realized after getting over some creeping burnout is that:

  • It’s frequently more challenging than ordinary dev work and it helps to keep my skillset sharp now that I’m officially a “real architect” again
  • I get to interact with a lot of smart folks and learn about a lot of other kinds of development approaches and projects. That’s pretty key for me because I haven’t been able to do many development conferences or events the past several years
  • The OSS projects are the one professional thing I get to have control over
  • I just enjoy doing it

I wrote a post in January trying to lay out for myself what I hoped or planned to do this year in the various OSS projects I run. At the halfway point of the year, I just wanna do a little update and see for myself where and how plans have changed.

  • Jasper – The project doesn’t have any real adoption yet, but I think it’s rounding into shape with some compelling features and qualities for microservice development in .Net and reliable messaging. I should have a v0.9 release out shortly with quite a few improvements that went in this spring before I changed jobs in May. Jasper will hopefully hit 1.0 before the end of the year. In terms of development work remaining, I might play around with flushing out the FubuMVC-style HTTP service routing as an alternative to MVC. I also hope to add quite a bit of integration with Jasper to Azure technologies as a learning exercise for myself to finally get some cloud computing skills and join the modern world.
  • Lamar (was BlueMilk) – Lamar 1.0 was released a couple weeks ago and I’ve had plenty of early user feedback that’s already led to some fixes. I released Lamar 1.1 yesterday that specifically targets the “cold start” time for applications using Lamar. This release especially improves the start time for ASP.Net Core applications using Lamar
  • Marten – Of all the things I work on, Marten has the most adoption and the biggest community by far, so I’ve mostly just tried to keep my head above water taking in pull requests and doing occasional bug fixes. If this week goes well, I’ll be starting preliminary work on a Marten 3.0 release for later this year to try to clear out the backlog of feature requests. My goal for Marten this year is to somehow whittle the open GitHub issue list down to a single page and keep it there.
  • Storyteller – Storyteller is the one project of mine that I actually get to regularly use.  I’m hoping to use it extensively on a project at work for Behavior Driven Development type specifications with our client’s business logic. I released a v5 earlier this year that just streamlined the command line usage and getting started story for new projects that target the latest .Net SDK project system. If the year goes well, I’d like to do a rewrite of the specification editor user interface. This is partially to add some missing functionality Storyteller needs to be truly usable by non-developers, but mostly to give me a chance to level up in the latest Javascript tools.
  • AlbaAlba is a little library that helps you write HTTP contract tests against ASP.Net Core applications. The obvious comparison in .Net is to TestServer in ASP.Net Core, but I’d say it’s more like Pact from Ruby or PlaySpecification in Scala. I just released Alba.AspNetCore2 v1.4.1 that made Alba work with ASP.Net Core 2.1. I might get into Alba this year and put it on top of TestServer and call it a big bag of extensions for TestServer instead of being its own thing (even though they barely overlap in functionality).
  • Oakton – Andy Dote made a pull request for asynchronous commands that formed the basis for the Oakton 1.5.0 release. At this point, I think Oakton is essentially done, and you’ll find it underneath several of the projects in the rest of this list
  • StructureMap — All I’m doing at this point is trying to answer user questions as they come in, and that flow has slowed way down. I’m asking folks to consider moving to Lamar or another IoC container for newer development.

Lamar 1.0: Faster, modernized successor to StructureMap

EDIT: 6/15/2018: Fixed an erroneous link and don’t you know it, there’s already a Lamar 1.0.2 up on Nuget (might take a second for indexing to catch up first) with some fixes  to user reported problems.

Lamar is a new OSS library written in C# that is a new IoC container meant to replace the venerable, but increasingly creaky StructureMap library. Lamar is also Jasper‘s “special sauce” that provides runtime code generation and compilation that helps make Jasper’s runtime pipeline very efficient compared to its competitors. You can happily use the code generation and compilation without the IoC functionality. Thank you to Mark Warpool, Jordan Zaerr, Mark Wuhrith and many others for their help and early feedback.

I’m happy to announce that Lamar and Lamar.Microsoft.DependencyInjection (the ASP.Net Core adapter) were both published as v1.0.0 to Nuget this morning. It’s been beaten up a bit by early adopters and I finished off the last couple features around type scanning that I wanted for a v1 feature set, so here we go. I’m pretty serious about semantic versioning, so you can take this release as a statement that the public API signatures are stable. The documentation website is completely up to date with the v1 API and ready to go. If you’re kicking the tires on Lamar and run into any trouble, check out the Gitter room for Lamar.

To get going, check out Lamar’s Getting Started page.

Lamar as IoC Container

To get started, just add Lamar to your project through Nuget.

Most of the time you use an IoC container these days, it’s probably mostly hidden inside of some kind of application framework. However, if you wanted to use Lamar all by itself you would first bootstrap a Lamar container with all its service registrations something like this:


var container = new Container(x =>
{
    // Using StructureMap style registrations
    x.For<IClock>().Use<Clock>();
    
    // Using ASP.Net Core DI style registrations
    x.AddTransient<IClock, Clock>();
    
    // and lots more services in all likelihood
});

Now, to resolve services from your container:


// StructureMap style

// Get a required service
var clock = container.GetInstance<IClock>();

// Try to resolve a service if it's registered
var service = container.TryGetInstance<IService>();

// ASP.Net Core style
var provider = (IServiceProvider)container;

// Get a required service
var clock2 = provider.GetRequiredService<IClock>();

// Try to resolve a service if it's registered
var service2 = provider.GetService<IService>();

Definitely note that the old StructureMap style of service resolution is semantically different than ASP.Net Core’s DI resolution methods. That’s been the cause of much user aggravation over the years.

 

Brief History of Lamar

I’ve become increasingly tired and frustrated with supporting StructureMap for the past several years. I also realized that StructureMap had fallen behind many other IoC tools in performance, and I really didn’t think that was going to be easy to address without some large scale structural changes in StructureMap.

Most of my ambition in OSS over the past couple years has been on Jasper (Marten was something we needed at work at the time and I had no idea it would turn out to be as successful as it has been). I’ve been planning for years to use Roslyn’s ability to generate code on the fly as a way to make Jasper’s runtime pipeline as fast as possible without losing much flexibility and extensibility. What is now Lamar’s code generation and compilation model was originally just a subsystem of Jasper for its runtime.

Because I was so focused on Jasper’s performance and throughput, I knew I would want to move beyond StructureMap as its IoC container. I tried the built in DI container from ASP.Net Core for a little bit, but its limited feature set was just too annoying.

Hence, Lamar was born as a new IoC container project called “‘BlueMilk” that would:

  • Completely comply with ASP.Net Core’s requirements for IoC container behavior and functionality
  • Retain quite a bit of functionality from StructureMap that I wanted
  • Provide an “off ramp” for folks that depend on StructureMap today now that I’m wanting to stop support on StructureMap
  • Ditch a lot of features from StructureMap that I never use personally and cause me a great deal of heartburn supporting
  • Support Jasper’s “Special Sauce” code weaving
  • Be as fast as possible

What’s Special about Lamar?

First off, how it works is unique compared to the at least 20-30 other OSS IoC containers in .Net.  is the usage of dynamic generation of C# code at runtime and subsequent compilation via Roslyn in memory. Most other containers build and compile Expressions to Func objects in memory. You might have to take my word for this, but that’s an awful model to work with efficiently.

Other containers depend on emitting IL and that’s just not something I ever care to do again.

It’s hard to explain, but when used in conjunction with Jasper, Lamar can in many cases use inline code generation to completely replace any kind of service location calls in Jasper’s runtime handling of messages or HTTP requests.

Why would I use this over the built in DI container?

Just to be clear, Lamar is completely compliant with all of ASP.Net Core’s DI behavioral rules and expectations. Lamar even directly implements several of the DI abstractions itself this time around rather than depending on adapter libraries that kinda, sorta force your IoC container to act like what the ASP.Net Core team arbitrarily decided was the new standard for everybody.

As you may already know, ASP.Net Core comes with a simplistic DI container out of the box and many teams are frankly going to be perfectly fine with that as it is. It’s fast and has a good cold start time.

All the same, I tried to live with the built in container as it was and got way too annoyed with all the features I missed from StructureMap, and hence, Lamar was born.

Lamar has a much richer feature set that I think absolutely has some significant value for productivity over the built in container including, but not limited to:

And for those of you hyperventilating because “oh my gosh, that sounds like some magic and [conference speaker/MVP/celebrity programmer] says that all code must be painfully explicit or the world is going to end!”, you’ll definitely want to check out all of Lamar’s diagnostic facilities that help you unravel problems and understand what’s going on within Lamar.

StructureMap to Lamar

Lamar supports a subset of StructureMap’s functionality and API. There are some behavioral differences to be aware of though:

  • The lifetime support is simplified and reflects the ASP.Net Core semantics rather than the old StructureMap lifecycle support
  • Registry is now ServiceRegistry
  • You can use a mix of StructureMap-style registration and ASP.Net Core style registrations natively
  • There is no semantic difference between Add() and Use() like there was in StructureMap. Last one in wins. Just like ASP.Net Core expects.
  • Lamar supports nested containers like most .Net frameworks expect, but child containers or profiles will probably not be supported
  • Lamar doesn’t yet support setter injection (if you want it, just be prepared for an “I take pull requests” response)
  • The Container.With().GetInstance() functionality is never going to be supported in Lamar. I’m theorizing that a formal auto-factory feature later will be a better alternative anyway
  • Lamar only supports decorators for interception so far

 

Other Information:

Lamar was originally called “BlueMilk”

 

 

 

Planning the Next Couple Marten Releases

I think we’ve got things lined up for a Marten 2.9 release in the next week with these highlights:

  • Fixes for netcoreapp2.1. A user found some issues with the Linq support so here we go.
  • The upgrade to Npgsql 4.0
  • Eliminating Netstandard 1.3 support. Marten will continue to target .Net 4.6 & Netstandard 2.0, and we’ll be running tests for net46, netcoreapp2.0, and netcoreapp2.1.
  • Some improvements on exception messages in the event store support
  • Upgrades to Newtonsoft.Json — but if the performance isn’t better than the baseline, I’ll leave it where it is

Brainstorming What’s Next

I’ve been admittedly putting  most of my OSS energy into other projects (Jasper/Lamar) for the past year, but the Marten community has been happily proceeding anyway. One of my goals for OSS work this year is to get the Marten issue list count (bugs, questions, and feature ideas) under 25 and keep it there so it’s only a single page in the GitHub website.

We’ve got a big backlog of issues and feature requests. For a potential Marten 2.9, I’d like to suggest:

That’s all for the document store, so now let’s talk about the event sourcing. I don’t have a huge amount of ideas because I don’t get to use it on real projects (yet), but here’s what I think just from responding to user problems:

  • The async daemon is up for some love, and I think I’ve learned some things from Jasper work that will be beneficial back in Marten. First, I think we can finally get a model where Marten itself can handle distributing the ownership of the projections between multiple application nodes so you can more easily deploy the async daemon. After a tip from one of my new colleagues at Calavista, I also want to pursue using “tombstone” events as placeholders on event capture failures to make the async daemon potentially quite a bit more efficient at runtime.
  • I think this would be an add on, but I have an idea for an alternative to ViewProjection that would let you write your projection as just methods on a class that take in any combination of the actual event, the IDocumentSession, the containing EventStream, or Event<T> metadata, then use Lamar to do its thing to generate the actual adapter to Marten’s projection model. I think this could end up being more efficient than ViewProjection is now at runtime, and certainly lead to cleaner code by eliminating the nested lambdas.
  • Event Store partitioning?
  • Event Store metadata extensions?

EDIT 6/8/2018: We had some discussions about this list on Gitter and I definitely forgot some big things here:

  • The async daemon and projections in general needs to be multi-tenancy friendly
  • Other users are interested in the multi-tenancy via database per tenant that got cut from 2.0 at the last minute

Any thoughts about any of this? Other requests? Comments are open, or head to Gitter to join the conversation about Marten.

 

Marten 3.0 with Sql Server Support????

I want to hold the line that there won’t be any kind of huge Marten 3.0 until there’s enough improvements to the JSON support in Sql Server vNext to justify an effort to finally make Marten database engine neutral. I’m also hoping that Marten 3.0 could completely switch all the Linq support to using queries based on SQL/Json too. See this blog post for why Marten does not yet support Sql Server.

Compiling Code At Runtime with Lamar – Part 2

In my previous post, I introduced Lamar‘s ability and utilities for generating code in memory and compiling that code into usable, in memory assemblies with the Roslyn compiler. In this post I’m going to try to explain the more complicated “frames” model with Lamar that provides the backbone for the related Jasper framework’s middleware and runtime pipeline strategy.

The purpose of the “frames” model is to be able to generate dynamic methods by declaring a list of logical operations in generated code via Frame objects, then let Lamar handle:

  • Finding any missing dependencies of those frames
  • Determine what the necessary variable inputs are
  • Ordering all the frames based on dependency order just prior to generating the code

Before diving into an example, here’s a little class diagram of the main types:

LamarCodeGenClassDiagram

The various types represent:

  • Frame – Named after the StackFrame objects within stack traces in .Net. Models a logical action done in the generated code. Concrete examples in Lamar or Jasper would be calling a method on an object, calling a constructor function, or specific frame objects to create wrapped transaction boundaries or exception handling boundaries.
  • Variable – pretty well what it sounds like. This type models a variable within the generated method, but also includes information about what Frame created it to help order the dependencies
  • IVariableSource – mechanism to “find” or create variables. Examples in Lamar include resolving a service from an IoC container, passing along a method argument, or the example below that tells you the current time
  • IMethodVariables – interface that is used by Frame classes to go find their necessary Variable dependencies.

Alrighty then, let’s make this concrete. Let’s say that we want to generate and use dynamic instances of this interface:

public interface ISaySomething
{
    void Speak();
}

Moreover, I want a version of ISaySomething that will call the following method and write the current time to the console:

public static class NowSpeaker
{
    public static void Speak(DateTime now)
    {
        Console.WriteLine(now.ToString("o"));
    }
}

Our dynamic class for ISaySomething will need to pass the current time to the now parameter of that method. To help out here, there’s some built in helpers in Lamar specifically to write in the right code to get the current time to a variable of DateTime or DateTimeOffset that is named “now.”

To skip ahead a little bit, let’s generate a new class and object with the following code:

// Configures the code generation rules
// and policies
var rules = new GenerationRules("GeneratedNamespace");

// Adds the "now : DateTime" variable rule to 
// our generated code
rules.Sources.Add(new NowTimeVariableSource());

// Start the definition for a new generated assembly
var assembly = new GeneratedAssembly(rules);

// Add a new generated type called "WhatTimeIsIt" that will
// implement the 
var type = assembly.AddType("WhatTimeIsIt", typeof(ISaySomething));

// Getting the definition for the method named "Speak"
var method = type.MethodFor(nameof(ISaySomething.Speak));

// Adding a frame that calls the NowSpeaker.Speak() method and
// adding it to the generated method
var @call = new MethodCall(typeof(NowSpeaker), nameof(NowSpeaker.Speak));
method.Frames.Add(@call);

// Compile the new code!
assembly.CompileAll();

After all that, if we interrogate the source code for the generated type above (type.SourceCode), we’d see this ugly generated code:

    public class WhatTimeIsIt : Lamar.Testing.Samples.ISaySomething
    {


        public void Speak()
        {
            var now = System.DateTime.UtcNow;
            Lamar.Testing.Samples.NowSpeaker.Speak(now);
        }

    }

Some notes about the generated code:

  • Lamar was able to stick in some additional code to pass the current time into a new variable, and call the Speak(DateTime now) method with that value.
  • Lamar is smart enough to put that code before the call to the method (that kind of matters here)
  • The generated code uses full type names in almost all cases to avoid type collisions rather than trying to get smart with using statements in the generated code

So now let’s look at how Lamar was able to add the code to pass along DateTime.UtcNow. First off, let’s look at the code that just writes out the date variable:

public class NowFetchFrame : SyncFrame
{
    public NowFetchFrame(Type variableType)
    {
        // there's some sleight of hand here that's marking
        // this new Variable as created by this frame object
        // so that the dependency relationship is made
        Variable = new Variable(variableType, "now", this);
    }
    
    public Variable Variable { get; }
    
    public override void GenerateCode(
        GeneratedMethod method, 
        ISourceWriter writer)
    {
        writer.WriteLine($"var {Variable.Usage} 
            = {Variable.VariableType.FullName}.{nameof(DateTime.UtcNow)};");
        Next?.GenerateCode(method, writer);
    }
}

In the frame above, you’ll see that the GenerateCode() method writes its code into the source, then immediately turns around and tells the next Frame – if there is one – to generated its code. As the last step to write out the new source code, Lamar:

  1. Goes through an effort to find any missing frames and variables
  2. Sorts them with a topological sort (what frames depend on what other frames or variables, what variables are used or created by what frames)
  3. Organizes the frames into a single linked list
  4. Calls GenerateCode() on the first frame

In the generated method up above, the call to NowSpeaker.Speak(now) depends on the now variable which is in turn created by the NowFetchFrame, and that’s enough information for Lamar to order things and generate the final code.

Lastly, we had to use a custom IVariableSource to teach Lamar how to resolve the now variable. That code looks like this:

public class NowTimeVariableSource : IVariableSource
{
    public bool Matches(Type type)
    {
        return type == typeof(DateTime) || type == typeof(DateTimeOffset);
    }

    public Variable Create(Type type)
    {
        if (type == typeof(DateTime))
        {
            return new NowFetchFrame(typeof(DateTime)).Variable;
        }

        if (type == typeof(DateTimeOffset))
        {
            return new NowFetchFrame(typeof(DateTimeOffset)).Variable;
        }

        throw new ArgumentOutOfRangeException(nameof(type), "Only DateTime and DateTimeOffset are supported");
    }
}

Out of the box, the Lamar + Jasper combination uses variable sources for:

  • Services from the internal IoC container of the application
  • Method arguments
  • Variables that can be derived from a method argument like HttpContext.Request
  • The “now” convention shown here

Summary

I don’t know how popular this thing is going to be, but it’s powering the dynamic code generation of Jasper’s runtime pipeline and it’s the key to Jasper’s efficiency compared to other .Net tools with similar functionality. The early feedback I got was that this model was very abstract and hard to follow. I’m open to suggestions, but the very nature of needing to do the recursive dependency detection and ordering kind of necessitates a model like this in my opinion.

Compiling Code At Runtime with Lamar – Part 1

This code was originally written and proven out in the related Marten and described in a post titled Using Roslyn for Runtime Code Generation in Marten. This code was ripped out of Marten itself, but it’s happily running now in Lamar a couple years later.

As some of you know, I’ve been working on a new library called Lamar that I mean to be the next generation replacement for the venerable, but creaky StructureMap library. Besides the IoC Container support though, Lamar also provides some tooling and a model to generate and compile code at runtime, then ultimately load and use the newly generated types.

If all you want to do is take some C# code and compile that in memory to a new, in memory assembly, you can use
the Lamar.Compilation.AssemblyGenerator class.

Let’s say that you have a simple interface in your system like this:

    public interface IOperation
    {
        int Calculate(int one, int two);
    }

Next, let’s use AssemblyGenerator to compile code with a custom implementation of IOperation that we’ve generated
in code:

        [Fact]
        public void generate_code_on_the_fly()
        {
            var generator = new AssemblyGenerator();

            // This is necessary for the compilation to succeed
            // It's exactly the equivalent of adding references
            // to your project
            generator.ReferenceAssembly(typeof(Console).Assembly);
            generator.ReferenceAssembly(typeof(IOperation).Assembly);

            // Compile and generate a new .Net Assembly object
            // in memory
            var assembly = generator.Generate(@"
using Lamar.Testing.Samples;

namespace Generated
{
    public class AddOperator : IOperation
    {
        public int Calculate(int one, int two)
        {
            return one + two;
        }
    }
}
");

            // Find the new type we generated up above
            var type = assembly.GetExportedTypes().Single();
            
            // Use Activator.CreateInstance() to build an object
            // instance of our new class, and cast it to the 
            // IOperation interface
            var operation = (IOperation)Activator.CreateInstance(type);

            // Use our new type
            var result = operation.Calculate(1, 2);
         
            result.ShouldBe(3);
        }

There’s only a couple things going on in the code above:

  1. I added an assembly reference for the .Net assembly that holds the IOperation interface
  2. I passed a string to the ​GenerateCode() method, which successfully compiles my code and hands me back a .Net Assembly object
  3. Load the newly generated type from the new Assembly
  4. Use the new IOperation

If you’re not perfectly keen on doing brute force string manipulation to generate your code, you can
also use Lamar’s built in ISourceWriter to generate some of the code for you with
all its code generation utilities:

[Fact]
public void generate_code_on_the_fly_using_source_writer()
{
    var generator = new AssemblyGenerator();

    // This is necessary for the compilation to succeed
    // It's exactly the equivalent of adding references
    // to your project
    generator.ReferenceAssembly(typeof(Console).Assembly);
    generator.ReferenceAssembly(typeof(IOperation).Assembly);


    var assembly = generator.Generate(x =>
    {
        x.Namespace("Generated");
        x.StartClass("AddOperator", typeof(IOperation));
        
        x.Write("BLOCK:public int Calculate(int one, int two)");
        x.Write("return one + two;");
        x.FinishBlock();  // Finish the method
        
        x.FinishBlock();  // Finish the class
        x.FinishBlock();  // Finish the namespace
    });

    var type = assembly.GetExportedTypes().Single();
    var operation = (IOperation)Activator.CreateInstance(type);

    var result = operation.Calculate(1, 2);

    result.ShouldBe(3);
}

In Part 2, I’ll talk about the “frames” model that’s heavily used within Jasper (shown in this post).

Scheduled or Delayed Message Execution in Jasper

This is definitely not a replacement for something like Hangfire, but it’s very handy for what it does. 

Here’s a couple somewhat common scenarios in an event driven or messaging system:

  • Handling a message failed, but with some kind of problem that might be resolved if the message is retried later in a few seconds or maybe even minutes
  • A message is received that starts a long running process of some kind, and you may want to schedule a “timeout” process later that would send an email to users or do something to escalate the process if it has not finished by the scheduled time

For these kinds of use cases, Jasper supports the idea of scheduled execution, where messages can be sent with a logical “execute this message at this later time.”

Retry Later in Error Handling

The first usage of scheduled execution is in message handling error policies. Take this example below where I tell Jasper to retry handling an incoming message that fails with a TimeoutException again after a 5 second delay:

public class GlobalRetryApp : JasperRegistry
{
    public GlobalRetryApp()
    {
        Handlers
            .OnException<TimeoutException>()
            .RetryLater(5.Seconds());
    }
}

Behind the scenes, the usage of the RetryLater()method causes Jasper to schedule the incoming message for later execution if that error policy kicks in during processing.

Scheduling Messages Locally

To schedule a message to be processed by the current system at a later time, just use the IMessageContext.Schedule() method as shown below:

public async Task schedule_locally(IMessageContext context, Guid issueId)
{
    var timeout = new WarnIfIssueIsStale
    {
        IssueId = issueId
    };

    // Process the issue timeout logic 3 days from now
    // in *this* system
    await context.Schedule(timeout, 3.Days());
}

This method allows you to either express an exact time or to use a TimeSpan argument for delayed scheduling. Either way, Jasper ultimately stores the scheduled message against a UTC time. IMessageContext is the main service in Jasper for sending and executing messages or commands. It will be registered in your IoC container for any Jasper application.

Sending Scheduled Messages to Other Systems

To send a message to another system that should wait to execute the message on its end, use this syntax:

public async Task send_at_5_tomorrow_afternoon_yourself(IMessageContext context, Guid issueId)
{
    var timeout = new WarnIfIssueIsStale
    {
        IssueId = issueId
    };

    var time = DateTime.Today.AddDays(1).AddHours(17);


    // Process the issue timeout at 5PM tomorrow
    // Do note that Jasper quietly converts this
    // to universal time in storage
    await context.Send(timeout, e => e.ExecutionTime = time);
}

Do note that Jasper immediately sends the message. For right now, the thinking is that the receiving application will be responsible for handling the execution scheduling. We may choose later to make this be the responsibility of the sending application instead to be more usable when sending messages to other systems that aren’t using Jasper.

Persistent Job Scheduling

The default, in memory message execution scheduling is probably good enough merely for delayed message processing retries as shown above, However, if you’re using the scheduled execution as part of your business workflow, you probably want to be using the durable message persistence. Today your two options are to use either Postgresql with Marten, or the new Sql Server backed message persistence.

With durable messaging, the scheduled messages are persisted to a backing database so they aren’t lost if any particular node is shut down or the whole system somehow crashes. Behind the scenes, Jasper just uses polling to check the database for any scheduled messages that are ready to execute, and pulls these expired messages into the local worker queues of a running node for normal execution.

The scheduled messages can be processed by any of the running nodes within your system, but we take some steps to guarantee that only one node will execute specific scheduled messages. Rather than using any kind of leader election, Jasper just takes advantage of advisory locks in Postgresql or application locks in Sql Server as a lightweight, global lock between the running nodes within your application. It’s a much simpler (read, less effort on my time) mechanism than trying to do some kind of leader election between running nodes. It also allows Jasper to better spread the work across all of the nodes.