Planifiez vos jobs en .Net Core avec FluentScheduler

Vous avez sans doute déjà eu le besoin d’exécuter du code à intervalles réguliers (par exemple 1 fois par heure, ou tous les jours à 06:00). Il existe plusieurs méthodes pour planifier ces jobs en .Net Core (par exemple, avec Quartz qui est assez connu). La solution que je vous propose utilise la librairie FluentScheduler. Je vous présente cette librairie car elle est réellement simple à mettre en place et je trouve cette solution élégante. Commençons par créer notre projet.

Ajoutons ensuite la librairie FluentScheduler.

Nous allons créer notre job planifié en deux étapes. La première étape est la création du job, et la deuxième est la planification de celui-ci.

Pour créer un job, il suffit de créer une classe qui implémentera l’interface IJob de la librairie FluentScheduler.

    public interface IJob
    {
        void Execute();
    }

Cette interface possède simplement une méthode Execute(). Il s’agit de la méthode qui sera appelée lorsque le job doit être exécuté. Créons à présent notre premier job.

    public class SayHiJob : IJob
    {
        public void Execute()
        {
            Console.WriteLine("Hi little parakeet!");
        }
    }

La deuxième étape est la planification de ce Job. Les jobs sont planifiés dans des registres. Nous allons créer une seconde classe qui héritera de la classe Registry fournie par la librairie FluentScheduler. Cette classe possède une méthode Schedule qui permet de planifier nos jobs.

Nous allons donc créer notre registre et planifier notre job SayHiJob pour qu’il démarre au lancement de l’application et ensuite, toutes les minutes.

    public class JobRegistry : Registry
    {
        public JobRegistry()
        {
            Schedule<SayHiJob>().ToRunNow().AndEvery(1).Minutes();
        }
    }

Il ne reste plus qu’à initialiser notre registre en utilisant la méthode statique JobManager.Initialize().

JobManager.Initialize(new JobRegistry());

Nous allons à présent créer un second job qui a besoin d’une dépendance, et nous allons voir comment nous pouvons injecter notre dépendance dans notre job. Commençons par créer notre dépendance.

    public class SayHiService : ISayHiService
    {
        public void SayHi()
        {
            Console.WriteLine("Hi from dependency.");
        }
    }

Créons ensuite notre job dans lequel nous injecterons notre dépendance.

    public class SayHiWithDependencyJob : IJob
    {
        private readonly ISayHiService _sayHiService;

        public SayHiWithDependencyJob(ISayHiService sayHiService)
        {
            _sayHiService = sayHiService;
        }

        public void Execute()
        {
            _sayHiService.SayHi();
        }
    }

Ajoutons ensuite notre job dans notre registre.

    public class JobRegistry : Registry
    {
        public JobRegistry()
        {
            Schedule<SayHiJob>().ToRunNow().AndEvery(1).Minutes();
            Schedule(new SayHiWithDependencyJob(new SayHiService())).ToRunOnceIn(10).Seconds();
        }
    }

Cela fonctionne, mais injecter nous-même nos dépendances, cela peut vite devenir compliqué. Nous allons donc utiliser le container IOC natif à .Net Core, et plus particulièrement l’interface IServiceProvider. Cette interface possède une classe GetRequiredService() qui permet de récupérer l’implémentation de la dépendance.

_sayHiService = serviceProvider.GetRequiredService<ISayHiService>();

Grâce à cette interface, peu importe le nombre de dépendances que possèdera notre job, il suffira simplement d’injecter IServiceProvider dans notre classe. Pour pouvoir injecter cette interface dans nos jobs, il faut au préalable injecter cette dernière dans notre registre. Modifions ce dernier pour injecter IServiceProvider.

    public class JobRegistry : Registry
    {
        public JobRegistry(IServiceProvider serviceProvider)
        {
            Schedule<SayHiJob>().ToRunNow().AndEvery(1).Minutes();
            Schedule(new SayHiWithDependencyJob(serviceProvider)).ToRunOnceIn(10).Seconds();
        }
    }

La dépendance IServiceProvider peut être obtenue dans la méthode ConfigureServices (Startup.cs dans un projet asp ou Program.cs dans le cadre d’une application console). Le paramètre services possède une méthode BuildServiceProvider() qui retourne cette dépendance. Il s’agit d’une méthode d’extension disponible dans la classe ServiceCollectionContainerBuilderExtensions (namespace Microsoft.Extensions.DependencyInjection). Nous allons donc récupérer cette dépendance via la méthode BuildServiceProvider et l’injecter dans notre méthode JobManager.Initialize() qui initialisera notre registre.

    class Program
    {
        static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseWindowsService()
                .ConfigureServices(ConfigureServicesDelegate);

        private static void ConfigureServicesDelegate(HostBuilderContext hostingContext, IServiceCollection services)
        {
            services.AddScoped<ISayHiService, SayHiService>();

            var serviceProvider = services.BuildServiceProvider();
            JobManager.Initialize(new JobRegistry(serviceProvider));
        }
    }

Vous savez à présent comment créer des jobs planifiés en .Net Core. Vous pouvez retrouver le code de cet article sur Github. N’hésitez pas à donner votre avis en commentaire ou me dire ce que vous utilisez pour vos jobs planifiés.

You may also like...

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *