• Stars
    star
    161
  • Rank 232,433 (Top 5 %)
  • Language
    C#
  • License
    MIT License
  • Created about 6 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Cron Scheduler for AspNetCore 2.x/7.x or DotNetCore 2.x/7.x Self-hosted

CronScheduler.AspNetCore

Build status NuGet Nuget feedz.io

Note: Pre-release packages are distributed via feedz.io.

Summary

The goal of this library was to design a simple Cron Scheduling engine that could be used with DotNetCore IHost or with AspNetCore IWebHost.

It is much lighter than Quartz schedular or its alternatives. The KISS principle was at the heart of the development of this library.

The CronScheduler can operate inside of any .NET Core GenericHost IHost thus makes it simpler to setup and configure but it always allow to be run inside of Kubernetes.

In addition IStartupJob was added to support async initialization of critical process before the IHost is ready to start.

Please refer to Migration Guide for the upgrade.

  • Install package for AspNetCore hosting .NET CLI
    dotnet add package CronScheduler.AspNetCore
  • Install package for IHost hosting .NET CLI
    dotnet add package CronScheduler.Extensions

Uses Crontab format for Jobs/Tasks schedules

This library supports up to 5 seconds job intervals in the Crontab format thank to HangfireIO/Cronos library.

You can use https://crontab-generator.org/ to generated needed job/task schedule.

Cron expression is a mask to define fixed times, dates and intervals. The mask consists of second (optional), minute, hour, day-of-month, month and day-of-week fields. All of the fields allow you to specify multiple values, and any given date/time will satisfy the specified Cron expression, if all the fields contain a matching value.

                                       Allowed values    Allowed special characters   Comment

┌───────────── second (optional)       0-59              * , - /                      
│ ┌───────────── minute                0-59              * , - /                      
│ │ ┌───────────── hour                0-23              * , - /                      
│ │ │ ┌───────────── day of month      1-31              * , - / L W ?                
│ │ │ │ ┌───────────── month           1-12 or JAN-DEC   * , - /                      
│ │ │ │ │ ┌───────────── day of week   0-6  or SUN-SAT   * , - / # L ?                Both 0 and 7 means SUN
│ │ │ │ │ │
* * * * * *

buymeacoffee

Give a Star!

If you like or are using this project to learn or start your solution, please give it a star. Thanks!

Demo Applications

  • CronSchedulerWorker - this example demonstrates how to use CronScheduler with new Microsoft .NET Core Workers Template
  • CronSchedulerApp - this example demonstrates how to use CronScheduler with AspNetCore applications.

There are two ways that options and jobs can be registered within the Scheduler Jobs.

  1. The basic and most effective way to register is via IConfiguration

This job registration is assuming that the name of the job and options name are the same.

    services.AddScheduler(ctx =>
    {
        ctx.AddJob<TestJob>();
    });
  1. The complex factory registration of the same cron job with different options
        services.AddScheduler(ctx =>
        {
            var jobName1 = "TestJob1";

            ctx.AddJob(
                sp =>
                {
                    var options = sp.GetRequiredService<IOptionsMonitor<SchedulerOptions>>().Get(jobName1);
                    return new TestJobDup(options, mockLoggerTestJob.Object);
                },
                options =>
                {
                    options.CronSchedule = "*/5 * * * * *";
                    options.RunImmediately = true;
                },
                jobName: jobName1);

            var jobName2 = "TestJob2";

            ctx.AddJob(
                sp =>
                {
                    var options = sp.GetRequiredService<IOptionsMonitor<SchedulerOptions>>().Get(jobName2);
                    return new TestJobDup(options, mockLoggerTestJob.Object);
                }, options =>
                {
                    options.CronSchedule = "*/5 * * * * *";
                    options.RunImmediately = true;
                },
                jobName: jobName2);
        });

Sample code for Singleton Schedule Job and its dependencies

    public class TorahQuoteJob : IScheduledJob
    {
        private readonly TorahQuoteJobOptions _options;
        private readonly TorahVerses _torahVerses;
        private readonly TorahService _service;

        /// <summary>
        /// Initializes a new instance of the <see cref="TorahQuoteJob"/> class.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="service"></param>
        /// <param name="torahVerses"></param>
        public TorahQuoteJob(
            IOptionsMonitor<TorahQuoteJobOptions> options,
            TorahService service,
            TorahVerses torahVerses)
        {
            _options = options.Get(Name);
            _service = service ?? throw new ArgumentNullException(nameof(service));
            _torahVerses = torahVerses ?? throw new ArgumentNullException(nameof(torahVerses));
        }

        // job name and options name must match.
        public string Name { get; } = nameof(TorahQuoteJob);

        public async Task ExecuteAsync(CancellationToken cancellationToken)
        {
            var index = new Random().Next(_options.Verses.Length);
            var exp = _options.Verses[index];

            _torahVerses.Current = await _service.GetVersesAsync(exp, cancellationToken);
        }
    }

Then register this service within the Startup.cs The sample uses Microsoft.Extensions.Http.Polly extension library to make http calls every 10 seconds.

    services.AddScheduler(builder =>
    {
        builder.Services.AddSingleton<TorahVerses>();

        // Build a policy that will handle exceptions, 408s, and 500s from the remote server
        builder.Services.AddHttpClient<TorahService>()
            .AddTransientHttpErrorPolicy(p => p.RetryAsync());
        builder.AddJob<TorahQuoteJob, TorahQuoteJobOptions>();
        
        // register a custom error processing for internal errors
        builder.AddUnobservedTaskExceptionHandler(sp =>
        {
            var logger = sp.GetRequiredService<ILoggerFactory>().CreateLogger("CronJobs");

            return
                (sender, args) =>
                {
                    logger?.LogError(args.Exception?.Message);
                    args.SetObserved();
                };
        });
    });

Sample code for Scoped or Transient Schedule Job and its dependencies

    public class UserJob : IScheduledJob
    {
        private readonly UserJobOptions _options;
        private readonly IServiceProvider _provider;

        public UserJob(
            IServiceProvider provider,
            IOptionsMonitor<UserJobOptions> options)
        {
            _options = options.Get(Name);
            _provider = provider ?? throw new ArgumentNullException(nameof(provider));
        }

        public string Name { get; } = nameof(UserJob);

        public async Task ExecuteAsync(CancellationToken cancellationToken)
        {
            // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.2&tabs=visual-studio#consuming-a-scoped-service-in-a-background-task
            using var scope = _provider.CreateScope();
            var userService = scope.ServiceProvider.GetRequiredService<UserService>();

            var users = userService.GetUsers();

            foreach (var user in users)
            {
                await userService.AddClaimAsync(user, new Claim(_options.ClaimName, DateTime.UtcNow.ToString()));
            }
        }
    }

Then register this service within the Startup.cs

        services.AddScheduler(builder =>
        {
            builder.Services.AddScoped<UserService>();
            builder.AddJob<UserJob, UserJobOptions>();

        // register a custom error processing for internal errors
        builder.AddUnobservedTaskExceptionHandler(sp =>
        {
            var logger = sp.GetRequiredService<ILoggerFactory>().CreateLogger("CronJobs");

            return
                (sender, args) =>
                {
                    logger?.LogError(args.Exception?.Message);
                    args.SetObserved();
                };
        });
        });

IStartupJobs to assist with async jobs initialization before the application starts

There are many case scenarios to use StartupJobs for the IWebHost interface or IGenericHost. Most common case scenario is to make sure that database is created and updated. This library makes it possible by simply doing the following:

  • In the Program.cs file add the following:
        public static async Task Main(string[] args)
        {
            var host = CreateWebHostBuilder(args).Build();

            // process any async jobs required to get the site up and running
            await host.RunStartupJobsAync();

            host.Run();
        }
  • Register the startup job in Program.cs or in Startup.cs file.
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
    return WebHost.CreateDefaultBuilder(args)
            .ConfigureServices(services =>
            {
                services.AddStartupJob<SeedDatabaseJob>();
            })
            .ConfigureLogging((context, logger) =>
            {
                logger.AddConsole();
                logger.AddDebug();
                logger.AddConfiguration(context.Configuration.GetSection("Logging"));
            })
            .UseStartup<Startup>();
}

Background Queues

In some instances of the application the need for queuing of the tasks is required. In order to enable this add the following in Startup.cs.

    services.AddBackgroundQueuedService();

Then add sample async task to be executed by the Queued Hosted Service.

    public class MyService
    {
        private readonly IBackgroundTaskQueue _taskQueue;

        public MyService(IBackgroundTaskQueue taskQueue)
        {
            _taskQueue = taskQueue;
        }

        public void RunTask()
        {
            _taskQueue.QueueBackgroundWorkItem(async (token)=>
            {
                // run some task
                await Task.Delay(TimeSpan.FromSeconds(10), token);
            }});
        }
    }

License

MIT License Copyright (c) 2017-2022 King David Consulting LLC

More Repositories

1

Bet.AspNetCore

Large Collection of Extensions and AspNetCore projects for ML.NET models and integration
C#
46
star
2

CometD.NetCore.Salesforce

CometD Salesforce Implementation.
C#
46
star
3

CometD.NetCore

CometD for use with Salesforce Platform Events
C#
24
star
4

NetCore.HashiCorp.Vault

Securing with HashiCorpVault in Kubernetes
C#
18
star
5

K8.DotNetCore.Workshop

Kubernates and DotNetCore Workshop demonstrates essentials skills for DotNetCore Developer
C#
16
star
6

Bet.Extensions.Emet

RulesEngine for DotNetCore Applications
C#
10
star
7

win10andwsldev

Windows 11 with Windows Linux Subsystem (WSL) Development
Shell
10
star
8

Bet.BuildingBlocks.SalesforceEventBus

Building Blocks for the Event Bus implementations for Salesforce Platform events.
C#
10
star
9

aspnetcore-angular-realworld-example-app

Asp.net core application using SPA JavascriptServices to serve Angular5+ app
C#
9
star
10

Linq.Dynamic

System.Linq.Dynamic Library for .NET Core
C#
8
star
11

Bet.Extensions.AuthorizeNet

AuthorizeNet DotNetCore Implementation
C#
7
star
12

Bet.Extensions.Resilience

DotNetCore Resilience Framework for Kubernetes Cluster
C#
7
star
13

Bet.BuildingBlocks

DotNetCore Clean Architecture Building Blocks
C#
5
star
14

openhack-containers-2021

Microsoft Containers Openhack
C#
4
star
15

docker

Docker Images for Docker Hub
C#
4
star
16

FeatureManagementWorkshop

The workshop that focuses on how to use Feature Management And Azure App Configuration in AspNetCore and DotNetCore Applications.
JavaScript
4
star
17

Bet.Extensions.Templating

Bet.Extensions.Templating repo for most common projects templates for DotNetCore
C#
4
star
18

Bet.Extensions.Legacy

ASP.Net WebForms, MVC4, WebApi2 packages to provide support for DotNetCore Dependency Injection (DI) and other new tech goodness.
JavaScript
4
star
19

Bet.Extensions.Walmart

Walmart Seller Library
C#
3
star
20

Bet.Notifications

DotNetCore Notification library to send emails, sms messages
HTML
3
star
21

Bet.AspNetCore.Minimal.Apis

AspNetCore 6.0 Minimal Apis Sample Code
C#
3
star
22

TodoAppReactAspNetCore

React with AspNetCore 6.0
JavaScript
3
star
23

Bet.CodeAnalyzers

DotNetCore Code Analyzers
C#
3
star
24

Bet.Extensions.Wkhtmltopdf

DotNetCore Wkhtmltopdf
C#
3
star
25

ionic-typescript-seed

Ionic Typescript Seed project provides with boilerplate functionality for the Ionic Applications. Angular 1.x written in TypeScript and also Gulpfile.ts that enables the template to provide with strong typing for the entire project.
TypeScript
3
star
26

Bet.AspNetCore.FluentValidation

AspNetCore FluetValidation Samples
C#
2
star
27

CSharpToPythonLearning

C# Developer's Exciting Journey into Python World 🐍
Jupyter Notebook
2
star
28

Moedim.Microservices

The collection of libraries for developing Microservices with Microsoft .NET Core
C#
2
star
29

Moedim.AzureVault

Azure KeyVault with prefixes
C#
2
star
30

AppAuthentication

DotNetCore CLI tool for Local Docker Containers Access to Azure Resources via Microsoft Managed Identity
C#
1
star
31

privatemobile-pixel3a-ubuntutouch-conversion

Empowering Privacy and Independence on Pixel 3a with Ubuntu Touch
1
star
32

Bet.Azure

Azure specific DoNetCore repo
C#
1
star
33

Bet.Google.ShoppingContent

Google Shopping Content for DotNetCore
C#
1
star
34

SelfReferencingExample

EfCore Self Referencing Example
C#
1
star
35

Bet.Extensions

A collection of projects that provides with K8s support for DotNetCore projects.
C#
1
star
36

BlazorLab

Blazor Learning
C#
1
star
37

Bet.Extensions.Shopify

Shopify Admin APIs with DotNetCore or AspNetCore
C#
1
star
38

svelte-workshop

Learning Svelte
JavaScript
1
star
39

react-templates

ReactJs Templates
TypeScript
1
star
40

vscode-azure-pack

Azure Cloude Dev Pack VS Code https://code.visualstudio.com
Dockerfile
1
star
41

dotnet-cosmosdb

DotNet Core Cosmosdb sample code
C#
1
star
42

bet.ks8s

C#
1
star
43

vscode-dotnetcore-pack

.NET Core Dev Pack VS Code https://code.visualstudio.com
Dockerfile
1
star
44

blazor-workshop

Hands-on Walk-tru for blazor-workshop
CSS
1
star
45

TenantTokenFlow

TenantTokenFlow enables seamless token generation & directory management across multiple tenants. Capture user tokens & create app registrations, users, & groups within directories
Python
1
star