All notable changes to NCronJob will be documented in this file. The project adheres to Semantic Versioning.
v4.10.1 - 2026-03-31
- Fixed duplicate job execution caused by system timers firing slightly before the scheduled cron time, resulting in the same cron slot being scheduled again. Reported by @RShergold in #327. Fixed by @linkdotnet.
v4.10.0 - 2026-03-30
OnlyIfon top-level job configuration.
- Bump many packages to latest version
v4.9.0 - 2025-12-28
OnlyIffor child jobs to not trigger based on a predicate.
v4.8.1 - 2025-12-28
OnlyIfto not trigger jobs based on a predicate. Reported by @amithegde in #328. Fixed by @linkdotnet.
v4.7.0 - 2025-11-22
- Native support for .NET 10.
- Fixed race condition in
JobExecutionProgressObserverthat could cause test hangs on .NET 9.0 in resource-constrained environments. Reported by @nulltoken in #125.
v4.6.0 - 2025-09-02
- Teach
JobOptionBuilderto only accept parameters. By @nulltoken in #241. - Teach
JobOptionBuilderto allow configuration of a startup job. By @nulltoken in #289.
- Deprecate
IStartupStage.RunAtStartup(). By @nulltoken in #289.
v4.5.4 - 2025-06-14
- Removed
net10.0support as it doesn't play well with NuGet and stable semantic versioning releases. Reported by @nulltoken in #286
v4.5.3 - 2025-06-14
IJobExecutionContextexposes how the job was started. Reported by @kikisaeba in #261. Fixed by @linkdotnet
- Deprecate
DateTimeOffsetbased overloads inIInstantJobRegistry. By @nulltoken in #272.
v4.4.1 - 2025-03-27
- Allow the registration of the same untyped job with different names. Reported by @Mangatome in #253. Fixed by @nulltoken in #252 and #254.
v4.4.0 - 2025-03-10
- Make
IInstantJobRegistryaccept job names. By @nulltoken in #215. - Expose whether a scheduled job is enabled or not. By @nulltoken in #231.
- Make
IRuntimeJobRegistry.GetAllRecurringJobs()return the job type. By @nulltoken in #232. - Surface job name and type through
ExecutionProgress. By @nulltoken in #234. - Teach
JobOptionBuilderto add a cron expression to a named job. By @nulltoken in #244.
- Fix injection of context in dynamic jobs. By @nulltoken in #215.
- Teach
IRuntimeJobRegistry.RemoveJob()to cope with disabled jobs. By @nulltoken in #230.
v4.3.4 - 2025-02-25
- Ensure orchestration includes dependents of faulted jobs. Added in #195, by @nulltoken.
- Honor custom retry policies. Fixed in #204, by @nulltoken.
- Detect ambiguous jobs triggered through
IInstantJobRegistry. Fixed in #213, by @nulltoken.
v4.3.3 - 2025-01-31
- Fixing minor concurrency issues. By @nulltoken in #184.
v4.3.2 - 2025-01-27
- Fixed an issue where exception handlers aren't called when a job can't be created. Reported by @nulltoken in #177. Fixed by @linkdotnet in #179.
v4.3.1 - 2025-01-23
-
Allow a cron job to also run at startup. Added in #171, by @nulltoken.
-
Teach startup jobs to optionaly prevent the application start on failure. Added in #165, by @nulltoken.
- Prevent
RunAtStartup()from blindly decorating all jobs of the same type. Added in #170, by @nulltoken. - Use UTC format for logger output.
- Prevented
ObjectDisposedExceptionin various places. Reported by @nulltoken in #172. Fixed by @linkdotnet.
v4.2.0 - 2025-01-17
-
Expose an experimental basic job execution progress reporting hook. Added in #157, by @nulltoken.
-
Report additional
ExecutionStates (Cancelledremoved jobs andSkippeddependent jobs). Added in #162, by @nulltoken.
v4.1.0 - 2025-01-02
- Expose typed version of
DisableJob(). Added in #151, by @nulltoken. - Expose typed version of
EnableJob(). Added in #151, by @nulltoken.
- Teach
IInstantJobRegistrymembers to return the job correlation id. Changed in #153, by @nulltoken.
- Make
RemoveJob<TJob>()andRemoveJob(Type)remove all jobs of the given type. Fixed in #151, by @nulltoken. - Ensure
UpdateSchedule()behavior is consistent. Fixed in #151, by @nulltoken.
v4.0.2 - 2024-12-28
New v4 release with some new features and improvements. Check the v4 migration guide for more information.
- Optionally make startup jobs run early
IRuntimeRegistry.AddJobis now calledTryRegisterto better reflect its behavior.- Explicit handling of duplicates
- Make
UseNCronJobAsyncmandatory when startup jobs have been defined
v3.3.8 - 2024-11-16
- Added
net9.0release packages for hosting abstraction.
- Calling
AddJobmultiple times onIRuntimeRegistrytriggered duplicates. Reported by @vrohak in #139. Fixed by @linkdotnet - Calling
AddNCronJobmultiple times should register all jobs. Reported by @skarum in #138. Fixed by @linkdotnet
v3.3.5 - 2024-11-04
-
Ensure parameter handling is coherent. Fixed in #132, by @nulltoken.
-
Prevent
InstantJobRegistryfrom altering the content ofJobRegistry. Fixed in #131, by @nulltoken.
v3.3.4 - 2024-11-03
-
Ensure multiples schedules of the same job with different chains of dependent jobs are properly processed. Identified in #108, by @nulltoken.
-
Teach
IRuntimeJobRegistry.RemoveJob()to clean up potential dependent jobs. Fixes #107, by @nulltoken.
v3.3.3 - 2024-10-31
- Simplifications and refactoring of internal code. By @nulltoken.
v3.3.2 - 2024-10-27
AddJobduring runtime didn't reevaluate the execution list correctly. Reported by @IvaTutis in #100. Fixed by @linkdotnet.
- New
AddJob(Type jobType)overload. By @linkdotnet.
v3.2.0 - 2024-10-19
- Fixed an issue where registering multiple dependent jobs would only call the last one. Reported by @nulltoken in #101. Fixed by @linkdotnet.
v3.1.3 - 2024-10-17
- Global exception handlers. By @linkdotnet. Reported by @nulltoken.
- Expose
JobNameandJobTypeinIJobExecutionContext.
v3.0.3 - 2024-09-15
This is a new major version! A bit of cleanup! Check the v3 migration guide for more information.
- Created abstraction around
JobExecutionContextto allow for easier testing and mocking. Will now beIJobExecutionContext.
- Removed
enableSecondPrecisionas it is now inferred automatically.
v2.8.6 - 2024-08-29
- Dispose could still lead to issues when an exception was thrown inside a job/task.
v2.8.5 - 2024-08-18
- Disposing can lead to issues inside
StopAsync. Fixed by @linkdotnet.
v2.8.4 - 2024-06-23
- Dependent jobs where registered as singleton instead of scoped. Fixed by @linkdotnet.
v2.8.3 - 2024-06-20
- Identical Job Definitions will not lead to multiple instances of the job running concurrently. By @linkdotnet.
v2.8.2 - 2024-06-18
- Instantiating
JobExecutionContextis not obsolete to prevent build errors.
v2.8.1 - 2024-06-18
- Removed preview feature as users had to opt-in to use it.
v2.8.0 - 2024-06-18
- Allow dynamically adding, removing jobs, updating the schedule or parameter and getting the schedule for a given job. Done by @linkdotnet. Reported by @KorsG in #83
This release includes improvements to the way Jobs are scheduled included in PR #85 implemented by @falvarez1
- Improved scheduling accuracy by preventing jobs of different types from competing for the same queue.
- Long-running jobs of one type no longer affect other types, improving overall job scheduling and execution.
- Added notifications for job states and event hooks to enhance observability.
- Introduced queue notifications for better monitoring.
- Improved maintainability and concurrency handling.
v2.7.4 - 2024-06-03
- Anonymous jobs don't execute multiple times
v2.7.3 - 2024-06-01
- Don't depend on prerelease version in
net9.0
v2.7.2 - 2024-06-01
- Ability to add a timezone for a "minimal job".
- Run jobs automatically when a job either succeeded or failed allowing to model a job pipeline. By @linkdotnet.
builder.Services.AddNCronJob(options =>
{
options.AddJob<ImportData>(p => p.WithCronExpression("0 0 * * *")
.ExecuteWhen(
success: s => s.RunJob<TransformData>("Optional Parameter"),
faulted: s => s.RunJob<Notify>("Another Optional Parameter"));
});- Minimal API for instant jobs and job dependencies. By @linkdotnet.
public void MyOtherMethod() => jobRegistry.RunInstantJob((MyOtherService service) => service.Do());- Replace
Microsoft.Extensions.HostingwithMicrosoft.Extensions.Hosting.Abstractionsfor better compatibility. Reported by @chrisls121 in #74. Implemented by @linkdotnet.
v2.6.1 - 2024-05-25
This release has the same changes as 2.6.0 but fixes an issue in the release pipeline.
- The NuGet.org "Release Notes" section will from now on be empty. It will contain a link to the releases.
v2.6.0 - 2024-05-25
- API signature improvements - Enhanced the job scheduling framework with new classes and interfaces to better support job lifecycle management, including startup configuration and notification handling. This includes the introduction of
StartupStage<TJob>,NotificationStage<TJob>,IJobStage,IStartupStage<TJob>, andINotificationStage<TJob>. #70 By @falvarez1
- Startup jobs - Run a job when the application starts. #70 By @falvarez1
- Sample project - Added a sample project to demonstrate Startup Jobs. #70 By @falvarez1
v2.5.0 - 2024-05-21
- Instant jobs are executed with the highest priority.
- If an instant job is executed that is not registered, it will throw an exception instead of silently ignoring it.
v2.4.6 - 2024-05-21
- Retry/Concurrency Attributes where ignored
v2.4.5 - 2024-05-20
- Readded public constructor for
JobExeuctionContextto make it unit testable
- Regex Indicator for cron expressions (IDE support)
v2.4.4 - 2024-05-20
- New minimal API to register jobs. By @falvarez1 Jobs can be defined via a simple lambda:
builder.Services.AddNCronJob((ILoggerFactory factory, TimeProvider timeProvider) =>
{
var logger = factory.CreateLogger("My Job");
logger.LogInformation("Hello World - The current date and time is {Time}", timeProvider.GetLocalNow());
}, "*/5 * * * * *");- Instant jobs did ignore the concurrency attribute and global concurrency settings. Fixed by @linkdotnet. Reported by @KorsG in #52
v2.3.2 - 2024-05-08
- Scheduler took local time instead of UTC as base. By @falvarez1
v2.3.1 - 2024-05-07
- TimeZone Support implemented by @falvarez1 in PR #22.
v2.2.1 - 2024-05-05
- Ability to schedule a job to run after a specific delay.
- Ability to schedule a job to run at a specific time.
v2.1.4 - 2024-05-01
- Retry Mechanism: Improved robustness of job executions, especially in cases of transient failures. Includes exponential backoff and fixed interval strategies.
- Concurrency Control: Introduced a
SupportsConcurrencyattribute to provide fine-grained control over the concurrency behavior of individual jobs. This attribute allows specifying the maximum degree of parallelism. - New WaitForJobsOrTimeout: Added an enhanced version of
WaitForJobsOrTimeoutto the Tests project that allows time advancement for each run, providing more precise control over test execution timing. - Cancellation Support: Jobs now support graceful cancellation during execution and SIGTERM.
- Concurrency Management: Implemented improved global concurrency handling techniques within
CronScheduler. This change enhances flexibility and scalability in managing job executions. - Async Job Executions: Job executions are now fully async from the moment the scheduler triggers the job, ensuring better performance and resource utilization.
- Test Framework Bugs: Addressed specific bugs in the testing framework, ensuring that all tests are now passing and provide reliable results.
- CRON jobs that are scheduled more than 50 days in the future did throw an exception.
- Support for concurrent jobs and retries, as well as overall improvements, implemented by @falvarez1 in PR #21.
v2.0.5 - 2024-04-19
- Implementation of the scheduling. Better performance and closed some memory leaks
- Throw exception if job cannot be resolved with dependencies from the DI container. Reported and implemented by @skarum in #23
v2.0.4 - 2024-04-16
- Don't log running jobs twice. Reported by @ryanbuening. Fixed by @linkdotnet
v2.0.3 - 2024-04-15
With v2 the overall API was cleaned up and made more consistent. AddNCronJob and AddCronJob are merged into one service defintion:
- The IDE can help with RegEx pattern thanks to the
StringSyntaxAttribute. - Added more code documentation (xmldoc) with many examples to rely less on the README.
- In
v1one would define as such:
services.AddNCronJob();
services.AddCronJob<PrintHelloWorld>(options =>
{
options.CronExpression = "* * * * *";
options.Parameter = "Hello World";
});With v2 the CronExpression is moved towards the builder pattern and AddCronJob is merged into AddNCronJob:
services.AddNCronJob(options =>
{
options.AddJob<PrintHelloWorld>(j =>
{
j.WithCronExpression("* * * * *")
.WithParameter("Hello World");
});
});- Cleaned up
AddNCronJobto not accidentally build the service container
v1.0.2 - 2024-04-11
- Removed internal periodic timer so that instant jobs are really executed instantly and cron jobs on the correct time (rather than too late)
- The
IsolationLevelwas completely removed as jobs are executed in their own scope anyway. It behaves likeIsolation.NewTaskby default. TimerIntervalinNCronJobOptionswas removed as it no longer used.
v0.13.2 - 2024-03-29
- Smaller performance improvements
v0.13.1 - 2024-03-25
- Check if
IsolationLevelis in a valid range - otherwise it throws an exception - Small refactorings
v0.13.0 - 2024-03-23
- Moved
EnableSecondPrecisionfromAddNCronJobtoAddCronJobto allow for more granular control over the precision of the cron expression - When a job is not registered, a error is logged, but the execution of other jobs is not interrupted
v0.12.0 - 2024-03-22
- Breaking Change:
Runis now calledRunAsyncto reflect the asynchronous nature of the method Rundoesn't take an optionalCancellationTokenanymore, as this is passed in anyway.
v0.11.5 - 2024-03-22
v0.11.4 - 2024-03-21
- Ability to set cron expressions with second-level precision
- Support for
net9.0 - Support for Isolation Level to run jobs independent of the current scheduler
- Notification system that allows to run a task when a job is finished
v0.10.1 - 2024-03-19
- Every Job-Run has its own scope
v0.10.0 - 2024-03-18
- Ability to set the timer interval
AddCronJobregisters as scoped service instead of transient
v0.9.3 - 2024-03-18
AddCronJobregisters the job as transient instead of singleton
v0.9.2 - 2024-03-17
- Simplified much of the logic for scheduling
- Instant jobs weren't executed correctly
v0.9.1 - 2024-03-17
- Fixed some docs
v0.9.0 - 2024-03-17
- Initial Release of NCronJob with lots of features
- The ability to schedule jobs using a cron expression
- The ability to instantly run a job
- Parameterized jobs - instant as well as cron jobs!
- Integrated in ASP.NET - Access your DI container like you would in any other service