{"id":19101286,"url":"https://github.com/kdcllc/CronScheduler.AspNetCore","last_synced_at":"2025-04-18T18:32:13.879Z","repository":{"id":33234361,"uuid":"144164830","full_name":"kdcllc/CronScheduler.AspNetCore","owner":"kdcllc","description":"Cron Jobs Scheduler for Asp.Net Core 2.x-8.x or .Net Core 2.x-8.x Self-hosted ","archived":false,"fork":false,"pushed_at":"2024-07-27T01:39:38.000Z","size":947,"stargazers_count":175,"open_issues_count":2,"forks_count":22,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-09-27T06:25:12.933Z","etag":null,"topics":["asp-net-core","aspnet-core","aspnet-product","aspnetcore","asynchronous-tasks","background-worker","cron","cron-expression","cron-jobs","cronjob","crons","cronscheduler","crontab-format","dotnet-core","dotnetcore","hostedservices","scheduled-jobs","scheduler","scheduling","task-scheduler"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kdcllc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["kdcllc"],"custom":["https://www.buymeacoffee.com/vyve0og"]}},"created_at":"2018-08-09T14:35:04.000Z","updated_at":"2024-09-03T15:23:39.000Z","dependencies_parsed_at":"2023-01-15T00:02:10.106Z","dependency_job_id":null,"html_url":"https://github.com/kdcllc/CronScheduler.AspNetCore","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kdcllc%2FCronScheduler.AspNetCore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kdcllc%2FCronScheduler.AspNetCore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kdcllc%2FCronScheduler.AspNetCore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kdcllc%2FCronScheduler.AspNetCore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kdcllc","download_url":"https://codeload.github.com/kdcllc/CronScheduler.AspNetCore/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223270351,"owners_count":17117205,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asp-net-core","aspnet-core","aspnet-product","aspnetcore","asynchronous-tasks","background-worker","cron","cron-expression","cron-jobs","cronjob","crons","cronscheduler","crontab-format","dotnet-core","dotnetcore","hostedservices","scheduled-jobs","scheduler","scheduling","task-scheduler"],"created_at":"2024-11-09T03:53:14.240Z","updated_at":"2024-11-09T03:57:04.812Z","avatar_url":"https://github.com/kdcllc.png","language":"C#","funding_links":["https://github.com/sponsors/kdcllc","https://www.buymeacoffee.com/vyve0og"],"categories":["others","C# #"],"sub_categories":[],"readme":"# CronScheduler.AspNetCore\n\n![master workflow](https://github.com/github/docs/actions/workflows/master.yml/badge.svg)\n[![NuGet](https://img.shields.io/nuget/v/CronScheduler.AspNetCore.svg)](https://www.nuget.org/packages?q=CronScheduler.AspNetCore)\n![Nuget](https://img.shields.io/nuget/dt/CronScheduler.AspNetCore)\n[![feedz.io](https://img.shields.io/badge/endpoint.svg?url=https://f.feedz.io/kdcllc/cronscheduler-aspnetcore/shield/CronScheduler.AspNetCore/latest)](https://f.feedz.io/kdcllc/cronscheduler-aspnetcore/packages/CronScheduler.AspNetCore/latest/download)\n\n*Note: Pre-release packages are distributed via [feedz.io](https://f.feedz.io/kdcllc/cronscheduler-aspnetcore/nuget/index.json).*\n\n![I Stand With Israel](./img/IStandWithIsrael.png)\n\n## Summary\n\n**Unlock the Power of Simplified Cron Scheduling in Your .NET Core Apps**\n\nAre you tired of complex scheduling libraries holding you back from building scalable and efficient applications? Look no further! Introducing **CronScheduler**, a lightweight and easy-to-use library designed specifically for .NET Core `IHost` or `IWebHost`.\n\nBuilt with the KISS principle in mind, CronScheduler is a simplified alternative to Quartz Scheduler and its alternatives. With CronScheduler, you can easily schedule tasks using cron syntax and operate within any .NET Core GenericHost `IHost`, making setup and configuration a breeze.\n\nBut that's not all! We've also introduced **IStartupJob**, allowing for async initialization of critical processes before the host is ready to start. This means you can ensure your application is properly initialized and running smoothly, even in complex Kubernetes environments.\n\n**Benefits:**\n\n* Lightweight and easy-to-use library\n* Simplified scheduling with cron syntax\n* Operates within .NET Core GenericHost `IHost` or `IWebHost`\n* Async initialization support for critical processes with IStartupJob\n\n**Join the CronScheduler community today and start simplifying your application's scheduling needs!**\n\n\u003e\n\u003e **Please refer to [Migration Guide](./Migration.md) for the upgrade.**\n\u003e\n[![buymeacoffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/vyve0og)\n\n## Give a Star! :star:\n\nIf you like or are using this project to learn or start your solution, please give it a star. Thanks!\n\n## Installation\n\n- Install package for `AspNetCore` hosting .NET CLI\n\n```bash\n    dotnet add package CronScheduler.AspNetCore\n```\n\n- Install package for `IHost` hosting .NET CLI\n\n```bash\n    dotnet add package CronScheduler.Extensions\n```\n\n## Uses Crontab format for Jobs/Tasks schedules\n\nThis library supports up to 5 seconds job intervals in the Crontab format thank to [HangfireIO/Cronos](https://github.com/HangfireIO/Cronos) library.\n\nYou can use [https://crontab-generator.org/](https://crontab-generator.org/) to generated needed job/task schedule.\n\n### Cron format\n\nCron 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.\n\n                                           Allowed values    Allowed special characters   Comment\n\n    ┌───────────── second (optional)       0-59              * , - /                      \n    │ ┌───────────── minute                0-59              * , - /                      \n    │ │ ┌───────────── hour                0-23              * , - /                      \n    │ │ │ ┌───────────── day of month      1-31              * , - / L W ?                \n    │ │ │ │ ┌───────────── month           1-12 or JAN-DEC   * , - /                      \n    │ │ │ │ │ ┌───────────── day of week   0-6  or SUN-SAT   * , - / # L ?                Both 0 and 7 means SUN\n    │ │ │ │ │ │\n    * * * * * *\n\n## Demo Applications\n\n- [CronSchedulerWorker](./src/CronSchedulerWorker/) - this example demonstrates how to use `CronScheduler` with new Microsoft .NET Core Workers Template\n- [CronSchedulerApp](./src/CronSchedulerApp) - this example demonstrates how to use `CronScheduler` with AspNetCore applications.\n\nThere are two ways that options and jobs can be registered within the Scheduler Jobs.\n\n1. The basic and most effective way to register is via `IConfiguration`\n\nThis job registration is assuming that the name of the job and options name are the same.\n\n```csharp\n    services.AddScheduler(ctx =\u003e\n    {\n        ctx.AddJob\u003cTestJob\u003e();\n    });\n```\n\n2. The complex factory registration of the same cron job with different options\n\n```csharp\n        services.AddScheduler(ctx =\u003e\n        {\n            var jobName1 = \"TestJob1\";\n\n            ctx.AddJob(\n                sp =\u003e\n                {\n                    var options = sp.GetRequiredService\u003cIOptionsMonitor\u003cSchedulerOptions\u003e\u003e().Get(jobName1);\n                    return new TestJobDup(options, mockLoggerTestJob.Object);\n                },\n                options =\u003e\n                {\n                    options.CronSchedule = \"*/5 * * * * *\";\n                    options.RunImmediately = true;\n                },\n                jobName: jobName1);\n\n            var jobName2 = \"TestJob2\";\n\n            ctx.AddJob(\n                sp =\u003e\n                {\n                    var options = sp.GetRequiredService\u003cIOptionsMonitor\u003cSchedulerOptions\u003e\u003e().Get(jobName2);\n                    return new TestJobDup(options, mockLoggerTestJob.Object);\n                }, options =\u003e\n                {\n                    options.CronSchedule = \"*/5 * * * * *\";\n                    options.RunImmediately = true;\n                },\n                jobName: jobName2);\n        });\n```\n\n## Sample code for Singleton Schedule Job and its dependencies\n\n```csharp\n    public class TorahQuoteJob : IScheduledJob\n    {\n        private readonly TorahQuoteJobOptions _options;\n        private readonly TorahVerses _torahVerses;\n        private readonly TorahService _service;\n\n        /// \u003csummary\u003e\n        /// Initializes a new instance of the \u003csee cref=\"TorahQuoteJob\"/\u003e class.\n        /// \u003c/summary\u003e\n        /// \u003cparam name=\"options\"\u003e\u003c/param\u003e\n        /// \u003cparam name=\"service\"\u003e\u003c/param\u003e\n        /// \u003cparam name=\"torahVerses\"\u003e\u003c/param\u003e\n        public TorahQuoteJob(\n            IOptionsMonitor\u003cTorahQuoteJobOptions\u003e options,\n            TorahService service,\n            TorahVerses torahVerses)\n        {\n            _options = options.Get(Name);\n            _service = service ?? throw new ArgumentNullException(nameof(service));\n            _torahVerses = torahVerses ?? throw new ArgumentNullException(nameof(torahVerses));\n        }\n\n        // job name and options name must match.\n        public string Name { get; } = nameof(TorahQuoteJob);\n\n        public async Task ExecuteAsync(CancellationToken cancellationToken)\n        {\n            var index = new Random().Next(_options.Verses.Length);\n            var exp = _options.Verses[index];\n\n            _torahVerses.Current = await _service.GetVersesAsync(exp, cancellationToken);\n        }\n    }\n```\n\nThen register this service within the `Program.cs`:\n\n```csharp\nvar builder = WebApplication.CreateBuilder(args);\n\n// Add services to the container.\nbuilder.Services.AddScheduler(builder =\u003e\n{\n    builder.Services.AddSingleton\u003cTorahVerses\u003e();\n    builder.Services\n        .AddHttpClient\u003cTorahService\u003e()\n        .AddTransientHttpErrorPolicy(p =\u003e p.RetryAsync());\n\n    builder.AddJob\u003cTorahQuoteJob, TorahQuoteJobOptions\u003e();\n    builder.Services.AddScoped\u003cUserService\u003e();\n    builder.AddJob\u003cUserJob, UserJobOptions\u003e();\n\n    builder.AddUnobservedTaskExceptionHandler(sp =\u003e\n    {\n        var logger = sp.GetRequiredService\u003cILoggerFactory\u003e().CreateLogger(\"CronJobs\");\n        return (sender, args) =\u003e\n        {\n            logger?.LogError(args.Exception?.Message);\n            args.SetObserved();\n        };\n    });\n});\n\nbuilder.Services.AddBackgroundQueuedService(applicationOnStopWaitForTasksToComplete: true);\nbuilder.Services.AddDatabaseDeveloperPageExceptionFilter();\n\nbuilder.Services.AddStartupJob\u003cSeedDatabaseStartupJob\u003e();\nbuilder.Services.AddStartupJob\u003cTestStartupJob\u003e();\n\nbuilder.Logging.AddConsole();\nbuilder.Logging.AddDebug();\nbuilder.Logging.AddConfiguration(builder.Configuration.GetSection(\"Logging\"));\n\nvar app = builder.Build();\n\n// Configure the HTTP request pipeline.\nif (app.Environment.IsDevelopment())\n{\n    app.UseDeveloperExceptionPage();\n    app.UseMigrationsEndPoint();\n}\nelse\n{\n    app.UseExceptionHandler(\"/Home/Error\");\n    app.UseHsts();\n}\n\napp.UseHttpsRedirection();\napp.UseStaticFiles();\napp.UseCookiePolicy();\napp.UseAuthentication();\napp.UseRouting();\n\napp.MapControllers();\napp.MapDefaultControllerRoute();\napp.MapRazorPages();\n\nawait app.RunStartupJobsAsync();\nawait app.RunAsync();\n```\n\n\n## `IStartupJobs` to assist with async jobs initialization before the application starts\n\nThere are many case scenarios to use StartupJobs for the `IWebHost` interface or `IGenericHost`. The most common case scenario is to make sure that the database is created and updated.\nThis library makes it possible by simply doing the following:\n\n- In the `Program.cs` file add the following:\n\n```csharp\nvar builder = WebApplication.CreateBuilder(args);\n\n// Add services to the container.\nbuilder.Services.AddStartupJob\u003cSeedDatabaseStartupJob\u003e();\nbuilder.Services.AddStartupJob\u003cTestStartupJob\u003e();\n\nvar app = builder.Build();\n\n// Configure the HTTP request pipeline.\nawait app.RunStartupJobsAsync();\nawait app.RunAsync();\n```\n## Background Queues\n\nIn 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`.\n\n```csharp\n    services.AddBackgroundQueuedService();\n```\n\nThen add sample async task to be executed by the Queued Hosted Service.\n\n```csharp\n\n    public class MyService\n    {\n        private readonly IBackgroundTaskQueue _taskQueue;\n\n        public MyService(IBackgroundTaskQueue taskQueue)\n        {\n            _taskQueue = taskQueue;\n        }\n\n        public void RunTask()\n        {\n            _taskQueue.QueueBackgroundWorkItem(async (token)=\u003e\n            {\n                // run some task\n                await Task.Delay(TimeSpan.FromSeconds(10), token);\n            }});\n        }\n    }\n```\n\n## License\n\n[MIT License](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkdcllc%2FCronScheduler.AspNetCore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkdcllc%2FCronScheduler.AspNetCore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkdcllc%2FCronScheduler.AspNetCore/lists"}