v4 Migration Guide

This document describes the changes made in v4 of NCronJob and how to migrate from v3.

Version 4 of NCronJob introduces some breaking changes to improve the API.

UseNCronJob and UseNCronJobAsync methods

Following the classical ASP.NET pattern, the UseNCronJob and UseNCronJobAsync methods have been introduced to the IHost interface. The minimal setup now looks like this:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddNCronJob(...);

var app = builder.Build();
await app.UseNCronJobAsync();
app.Run();

Instead of the async method UseNCronJobAsync, you can also use the synchronous UseNCronJob method. The difference is that the async method returns a Task that you can await.

RunAtStartup method

The RunAtStartup method has a bit different semantics than before. All startup jobs are now executed when UseNCronJob or UseNCronJobAsync is called. This ensures that all startup jobs are completed before any other part of the application is executed.

AddNCronJob(Delegate) move to NCronJobExtensions

The AddNCronJob(Delegate) (Minimal API) was a different static class than the AddNCronJob(Action) version. This has been fixed by moving the AddNCronJob(Delegate) method to the NCronJobExtensions class. As most developers are not invoking those extensions via the static class, this should not affect most users. Otherwise the migration is simple:

- IServiceCollection.AddNCronJob(() => {}, "* * * * *");
+ NCronJobExtensions.AddNCronJob(services, () => {}, "* * * * *");

IRuntimeRegistry is more restrictive

In v3 the IRuntimeRegistry offered the ability to use the whole NCronJobOptionBuilder which led to confusion, especially if done something like this:

runtimeRegistry.AddJob(n => n.AddJob<MyJob>(...).RunAtStartup().AddExceptionHandler<MyHandler>());

It didn’t make sense to add a startup job during runtime. Also adding exception handlers during runtime was out of scope for this feature. Therefore the interface is more restrictive now and only allows to add jobs.

IRuntimeRegistrys AddJob is now called TryRegister

The AddJob method of the IRuntimeRegistry has been renamed to Register to better reflect its purpose and to avoid the convoluted naming.

- runtimeRegistry.AddJob(r => r.AddJob);
+ runtimeRegistry.TryRegister(r => r.AddJob);

Not only that there is another overload:

+ runtimeRegistry.TryRegister(r => r.AddJob, out Exception? exc);

The new TryRegister method returns a boolean indicating if the registration was successful and an exception if the registration failed. This can happen if the same configuration of a job is already configured (like same job type, with same cron expression and parameter).

Chaining was removed

Additionally, the chaining of the former Add (now TryRegister) method was removed. If the first job registration was successful, but the second failed, the first job was still registered. This seemed arbitrary and was removed.

Each chain should be its own TryRegister call now.

Registering duplicated jobs will lead to an exception during startup

Given the following job registration:

builder.Services.AddNCronJob(r => r.AddJob<MyJob>(p => p
    .WithCronExpression("* * * * *")
    .And
    .WithCronExpression("* * * * *")));

In v3 and earlier the second registration would have been ignored. In v4 this will lead to an exception. This is to prevent accidental misconfigurations. Especially because jobs, by default, are not executed in parallel without further configuration. If you want to register the same job multiple times, you can define a custom name for the job:

builder.Services.AddNCronJob(r => r.AddJob<MyJob>(p => p
    .WithCronExpression("* * * * *")
    .And
    .WithCronExpression("* * * * *").WithName("MyJob")));