Near-zero config .NET library that makes advanced application features like Task Scheduling, Caching, Queuing, Event Broadcasting, and more a breeze!
Introduces scheduling an invocable with extra parameters.
This release adds "sub-minute" task scheduling intervals:
EverySecond
EveryFiveSeconds
EveryTenSeconds
EveryFifteenSeconds
EveryThirtySeconds
Event broadcasting is great - but what if your event listeners are doing some heavy / long-winded tasks?
Using QueueBroadcast
you can queue an event to be broadcasted in the background so your app can continue to be responsive.
// This will broadcast the event whenever the queue is consummed in the background.
this._queue.QueueBroadcast(new OrderCreated(orderId));
Major change:
The functionality is the same, yet allows using Coravel in shared libraries, "business layers", etc. E.g. Any .NET Standard 2.0 + lib 😉
Removed dependency on Microsoft.AspNetCore.App
to use the respective "Abstraction" packages.
Breaking changes to how Coravel features are configured within the Configure
method in Startup.cs (see docs)
Fixed some internal issues with the events system.
event new
addedWhen
method (contributed by @papakaliati)The scheduler was the first Coravel feature - which was just a prototype built one day while I had some time to kill while my kids were asleep ;) I just wanted to see if it was possible for me to get a really basic version coded.
As the dotnet community has indicated there is some real interest in this project, the scheduler has naturally been due for a re-write - if it is to be used in actual projects.
These changes have also increased the number of unit tests in Coravel from over 100 to almost 600! Something that should help the community feel like Coravel is a reliable library to use.
Now the scheduler works like cron. Every minute the scheduled task checks the time and uses a cron expression to determine if it should run.
A side benefit is that we now have a Cron
method available for scheduling tasks.
I battled over whether or not to implement this myself. In the end, I decided that it was better not to add another dependency (especially since I couldn't find a library that was considered really trustworthy in this area).
I don't want to re-invent the wheel - I'm all for using third-party / NuGet packages others have made. But I want to ensure that whatever I do use has already been considered a trustworthy and reliable package (for example, I decided to include MailKit for the Mailer feature. MailKit is considered by everyone to be the .Net Core SMTP mailing go-to)
The collection of scheduled tasks were simply held in a List
. The scheduler allows scheduling tasks dynamically - while this isn't necessarily recommended (since these scheduled tasks will disappear after the application is closed) - it is possible. There may be some use-cases for this.
Anyways, using a List
in multi-threaded use cases is bad. So now the scheduler is using a ConcurrentBag
(among other internal enhancements such as using Task.WhenAll
, etc.).
I'm still considering other parallel processing enhancements (to fire scheduled tasks in true parallel), but for now, the changes are needed and moving the right direction.
Previously, all the scheduler config was done in ConfigureServices
. This has changed to allow additional features and an implementation that uses .Net Core's DI container more properly.
In ConfigureServices
:
services.AddScheduler()
Then in Configure
- all the existing configuration methods can be used:
app.UseScheduler(scheduler =>
{
scheduler.Schedule(
() => Console.WriteLine("Every minute during the week.")
)
.EveryMinute();
.Weekday();
});
Just like the point above, the queue had the same changes made:
In ConfigureServices
:
services.AddQueue();
In Configure
:
app
.ConfigureQueue()
.OnError(e =>
{
//.... handle the error
});
Coravel now exposes a concept of "Invocables". Basically, it's a class that can be "Invoked" (i.e. executed) asynchronously.
This allows us to create specific classes to do a certain "Job" in our system. These "jobs" can then be either scheduled or queued using a super simple syntax.
this._queue.QueueInvocable<GrabDataFromApiAndPutInDBInvocable>();
// or
scheduler
.Schedule<GrabDataFromApiAndPutInDBInvocable>()
.EveryTenMinutes();
New command: coravel invocable new [yourInvocable]
will generate a clean invocable all ready to go.
Sometimes you may have long running tasks (longer than 1 minute?). The normal behaviour of the scheduler is to simply fire off a task if it is due. What if you don't want a "due" task to execute if the previously executed one is still running?
scheduler
.Schedule<SomeInvocable>()
.EveryMinute()
.PreventOverlapping("SomeInvocable");