A Dynamic Task Scheduler for ASP.NET Core
Join the DZone community and get the full member experience.
Join For FreeThere are many task schedulers for ASP.NET. Two of the more famous ones are Quartz.NET and Hangfire. Both of these are amazing tools, and I have personally used Hangfire myself with great success. But, they both suffer from a lack of flexibility and/or complexity in usage.
Quartz.NET suffers from an overly complex API, based upon configuration files, in a difficult to understand format, giving you no syntax highlighting or AutoComplete when you declare your tasks. In addition, the amount of code required to actually create a simple task sometimes feels staggeringly large and unnecessarily complex. The fact that it was "ported" from Java shows as you try to learn its API.
So, even though it is an amazingly high-quality piece of work, it falls short on the most important feature any library and component arguably should have: Simplicity!
Hangfire on the other hand, is backed by a persistent database and a dashboard, allowing you to administrate your tasks in a GUI, and store them in your database. However, its main advantage also becomes its main disadvantage. Sometimes all you want is a simple component you can pull in through NuGet, invoke some methods on, and have some background tasks automatically created for you — being able to trust they'll be executed once their date is due.
Hangfire is simply too much, to be honest with you. In fact, Quartz.NET and Hangfire are in many ways complete opposites, and there is a need for some "middle ground" here. So, I created the Magic Scheduler.
The above image illustrates how you could create a task that should be repeated every Wednesday at 22:30. Of course, the above task simply creates a log entry with the content of "It is Wednesday today," but the stuff you don't see so easily in the above picture is the DSL capacities of this task scheduler.
The big black box in the image above accepts Hyperlambda, which is a .Net DSL, allowing you to easily tie into your existing C# code, to have some piece of C# snippet execute according to some pattern. Imagine the following C# code for instance:
using magic.node;
using magic.node.extensions;
using magic.signals.contracts;
namespace acme
{
[Slot(Name = "create-database-backup")]
public class CreateDatabaseBackup : ISlot
{
public void Signal(ISignaler signaler, Node input)
{
var databaseName = input.GetEx<string>();
/*
* Create backup of specified database here ...
*/
}
}
}
Notice the above attribute, which has a name of "create-database-backup." Then look at the following screenshot, and how Magic automatically gives you AutoComplete with the above slot as one of its suggestions.
Yup, whatever ISlot classes you declare in your own code, Magic's frontend will automatically give you AutoComplete, through your browser in your backend dashboard. In addition, you can also easily pass in arguments to your slots that you can reference from your C# code. This, of course, becomes a major advantage over the arcane and difficult to understand configuration format from Quartz.NET, especially for newcomers looking to simply create some sort of background task and have it executed once every blue moon or something.
Also, the tasks are created during runtime, without having to interrupt normal usage, allowing you to add, create, delete, and modify tasks in production. No need to compile C# code and restart your Web app. (For the record, click CTRL+SPACE to trigger the AutoCompleter in Magic's Hyperlambda editor.)
When you have declared your task's Hyperlambda, you can test it immediately, which will execute it on your main HTTP request thread, allowing you to step through your C# code. This allows you to verify that your task is actually working, before leaving it up to your scheduler, to execute it next Wednesday for instance - At which point it might or might not work. See the screenshot below, and notice its "Run" button. The below is how a task looks like when you view it, after having initially created it for the record.
Then you'll need some way to filter and search through your tasks, easily showing you all your upcoming tasks. Well, this is how that looks like in Magic.
Notice how you can stop the scheduler too if, for some reason, you no longer want any tasks to continue executing. But the last, and for me, the nicest thing about it, is that the DSL language you use to declare your task's content can also just as easily be used to declare the entire task. Yup, even declaring tasks themselves can be done using Hyperlambda. This allows you to distribute, for instance, your Magic installation such that it "out of the box" creates a bunch of default tasks.
This allows you to distribute Hyperlambda files in your pipeline that are executed during startup, creating a list of "default tasks" that are to be executed according to some repetition pattern. Below is a piece of Hyperlambda showing you how to do this.
scheduler.tasks.create:some-tuesday-task
description:This task will execute every tuesday at 10PM
repeat:Tuesday
time:"22:00"
.lambda
log.info:It is Tuesday today!
Pretty cool, huh ...?
I think so. Get the goods over here.
Or obtain a proprietary license here.
Further Reading
Opinions expressed by DZone contributors are their own.
Comments