dotnet-labs / serviceworkercronjob Goto Github PK
View Code? Open in Web Editor NEWSchedule Cron Jobs using HostedService in ASP.NET Core
License: MIT License
Schedule Cron Jobs using HostedService in ASP.NET Core
License: MIT License
Hello, i added a new Cronjob running every 10 minutes between 4 and 23 o'clock. When the job is running on 23:00:00 O'clock then the function GetNextOccurrence returned 23:10:00 but why? My cronjob sould only run from 4 - 23 o'clock.
service.AddCronJob<GDIEMailEventsCronjob>(c =>
{
c.CronExpression = @"*/10 * 4-23 * *";
c.CronJobType = CronJobType.GDI_EMAIL_EVENT;
});
public DateTime GetNextRunningTime(DateTime startTime)
{
return schedule.GetNextOccurrence(startTime);
}
How I can have control over jobs and manually start/stop themes?
Is is possible to do this?
I am accessing the Configuration in my DoWork.
For instance, a few of my jobs call internal web services/applications and I want to cleanly handle unlikely exceptions (such as a System.Net.Http.HttpRequestException).
I currently have an abstract base class DomainCronJob : CronJobService
, which calls an abstract method Run( CancellationToken cancellationToken );
. As expected, uncaught exceptions bubble up to the CrobJobService call to await DoWork( cancellationToken )
. I'm a little new to hosted services and was wondering if there was a reason you left out a generic try { await DoWork(...) } catch (Exception) {}
from this call / what you think the best course of action would be.
Hi Chan,
As far as i can tell, the current code base is unable to handle multiple registrations of the same cron object:
services.AddCronJob<MyCronJob>( c=> .... )
services.AddCronJob<MyCronJob>( c=> .... )
This questions was already asked by @markofranjic , but in this case, i'm not able to construct a single cron expression. I have two crons which cannot be simplified to one.
How would you suggest to change the code base to handle multiple cron job entries?
Hi Chan,
Could you please give me information if I can run more then one background jobs with same object of class.
For example. I need to run job at 21:00 and same job need to be run at 05:00?
I have tried
` services.AddCronJob(c =>
{
c.TimeZoneInfo = TimeZoneInfo.Local;
c.CronExpression = @"{21:00 Time Example}";
});
services.AddCronJob<MyCronJob>(c =>
{
c.TimeZoneInfo = TimeZoneInfo.Local;
c.CronExpression = @"{05:00 Time Example}";
});`
Regards
This service will fail if the timer-delay is more than 25 days. I need to run a job once a month and the timer throw a unhandled exception
Bug-Fix
You should use the system.threading.timer instead .
protected virtual async Task ScheduleJob(CancellationToken cancellationToken)
{
var next = _expression.GetNextOccurrence(DateTimeOffset.Now, _timeZoneInfo);
if (next.HasValue)
{
var delay = next.Value - DateTimeOffset.Now;
if (delay.TotalMilliseconds <= 0) // prevent non-positive values from being passed into Timer
{
await ScheduleJob(cancellationToken);
}
_timer = new System.Threading.Timer(async (state) =>
{
_timer.Dispose(); // reset and dispose timer
_timer = null;
if (!cancellationToken.IsCancellationRequested)
{
await DoWork(cancellationToken);
}
if (!cancellationToken.IsCancellationRequested)
{
await ScheduleJob(cancellationToken); // reschedule next
}
}, null, delay, new TimeSpan(0, 0, 0, 0, -1));
}
await Task.CompletedTask;
}
I have a cron job with the following cron schedule:
0 0 1 * *
This cron schedule indicates that the next occurrence will be At 12:00 AM, on day 1 of the month, today it is 10/03/2022 so the next occurence is 11/01/2022, the difference beetween today and the next execution in milliseconds is bigger than int.MaxValue causing the following exception:
System.ArgumentException: Invalid value '2478456815.9281' for parameter 'interval'.
at System.Timers.Timer..ctor(Double interval)
First - thank you for putting this out there - really great.
Regarding the ScheduleJob
method of the CronJobService
class:
If the DoWork
method has a significant execution time, it might be worth disposing and freeing up the timer before commencing (I realise it is a minuscule system resource, it just 'feels' more correct to me). Similarly the DoWork
task might be returning a completed task because it has detected the IsCancelationRequested
change to true - is it worth checking before creating the next iteration?
_timer.Elapsed += async (sender, args) =>
{
_timer.Dispose();
_timer = null;
if (!cancellationToken.IsCancellationRequested)
{
await DoWork(cancellationToken);
}
if (!cancellationToken.IsCancellationRequested)
{
await ScheduleJob(cancellationToken); // reschedule next
}
};
Root Cause:
_timer = new System.Timers.Timer(delay.TotalMilliseconds);
Here, the delay is the time between now and the next occurrence.
If this number delay.TotalMilliseconds
is greater than System.Int32.MaxValue
, the System.Timers.Timer
throws an ArgumentException.
In nutshell, the current solution does not work for any CRON Expression that results in delay.TotalMilliseconds
to be larger than System.Int32.MaxValue
.
Can someone help me in fixing this?
Hello,
I am here to request support for registering multiple instances of the same service, i.e. instead of creating one class for each Cron Expression, as mentioned in your original post, it is desirable to register as indicated by the code below
appsettings.json or equivalent
"CronServiceConfiguration": {
"ServiceSchedules":
[
"0 55-59/1 21 * * *",
"0/5 * 22 * * *"
]
}
Startup.cs class or equivalent
// Cron Jobs
IList<string> serviceSchedules = configuration.GetSection("CronServiceConfiguration:ServiceSchedules").Bind(serviceSchedules);
ArgumentNullException.ThrowIfNull(serviceSchedules);
foreach (string schedule in serviceSchedules)
{
services
.RegisterCronServiceInstance<CronService>(cronConfiguration =>
{
cronConfiguration.TimeZoneInfo = TimeZoneInfo.Local;
cronConfiguration.CronExpression = schedule;
cronConfiguration.CronFormat = CronFormat.IncludeSeconds;
});
}
As per Microsoft's recommendation, which you may read here, instead of calling
services.AddHostedService<TCronService>();
We would register each instance using
services.AddSingleton<ICronConfiguration<TCronService>>(cronConfiguration);
services.AddSingleton<IHostedService, TCronService>();
However, the main problem lies in the configurations.
The classes are registered ok as singletons, but they only read the latest registered configuration.
How can we ensure that each instance has the current registered configuration?
Any help would be appreciated.
Kind regards,
Paulo
Hi,
I followed this library and the codeburst which schedules and runs just fine but I have below issue with it.
When I run my Asp.Net Core Web API
in Windows 10
environments everything works as scheduled whereas the same same Web Api
when I deploy in Windows Server Core
, this schedule runs at every 15 mins.
Should I change any thing in the code?
Here is my options at startup.cs
.
services.AddCronJob<BackUpDBService>(c =>
{ // Currently it is running for every 15 mins in server which is wrong.
c.TimeZoneInfo = TimeZoneInfo.Local;
c.CronExpression = @"0 3 * * *";
});
First I wanted to say thank you for sharing. It's a really cool class. I love that it's simple but also pretty powerful.
Question:
Is there an EventHandler leak here (I think there is unless Dispose is unwiring that event)? Even though the _timer is Disposed of I think the EventHandler still needs to be unsubscribed from before that (not sure how to do that with a lambda, my solution was to make the event handler it's own function that way I could unsubscribe from it -= MyEvent
before Dispose
was called).
// This needs to be unsubscribed from before _timer is disposed.
_timer.Elapsed += async (sender, args) =>
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.