{"id":19992999,"url":"https://github.com/icsharp/Hangfire.RecurringJobExtensions","last_synced_at":"2025-05-04T12:30:35.295Z","repository":{"id":60774055,"uuid":"73913449","full_name":"icsharp/Hangfire.RecurringJobExtensions","owner":"icsharp","description":"Extensions for Hangfire to build RecurringJob automatically","archived":false,"fork":false,"pushed_at":"2018-11-17T15:44:17.000Z","size":62,"stargazers_count":185,"open_issues_count":12,"forks_count":36,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-03T20:18:05.862Z","etag":null,"topics":["cron-expression","hangfire","json-configuration","quartz","recurring-jobs"],"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/icsharp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-11-16T11:26:04.000Z","updated_at":"2025-04-22T22:31:46.000Z","dependencies_parsed_at":"2022-10-04T15:26:18.959Z","dependency_job_id":null,"html_url":"https://github.com/icsharp/Hangfire.RecurringJobExtensions","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icsharp%2FHangfire.RecurringJobExtensions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icsharp%2FHangfire.RecurringJobExtensions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icsharp%2FHangfire.RecurringJobExtensions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icsharp%2FHangfire.RecurringJobExtensions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/icsharp","download_url":"https://codeload.github.com/icsharp/Hangfire.RecurringJobExtensions/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252334018,"owners_count":21731314,"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":["cron-expression","hangfire","json-configuration","quartz","recurring-jobs"],"created_at":"2024-11-13T04:52:25.266Z","updated_at":"2025-05-04T12:30:34.798Z","avatar_url":"https://github.com/icsharp.png","language":"C#","funding_links":[],"categories":["C\\#"],"sub_categories":[],"readme":"# Hangfire.RecurringJobExtensions\n\n[![Official Site](https://img.shields.io/badge/site-hangfire.io-blue.svg)](http://hangfire.io)\n[![NuGet](https://buildstats.info/nuget/Hangfire.RecurringJobExtensions)](https://www.nuget.org/packages/Hangfire.RecurringJobExtensions/)\n[![Build status](https://ci.appveyor.com/api/projects/status/i02yxvu0mvhyv5nk?svg=true)](https://ci.appveyor.com/project/icsharp/hangfire-recurringjobextensions)\n[![License MIT](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT)\n\nThis repo is the extension for [Hangfire](https://github.com/HangfireIO/Hangfire) to build `RecurringJob` automatically.\nWhen app start, `RecurringJob` will be added/updated automatically.\nThere is two ways to build `RecurringJob`.\n\n- `RecurringJobAttribute` attribute\n- Json Configuration\n\n## Using RecurringJobAttribute\n\nWe can use the attribute `RecurringJobAttribute` to assign the interface/instance/static method.\n\n\n```csharp\npublic class RecurringJobService\n{\n    [RecurringJob(\"*/1 * * * *\")]\n    [Queue(\"jobs\")]\n    public void TestJob1(PerformContext context)\n    {\n        context.WriteLine($\"{DateTime.Now.ToString(\"yyyy/MM/dd HH:mm:ss\")} TestJob1 Running ...\");\n    }\n    [RecurringJob(\"*/2 * * * *\", RecurringJobId = \"TestJob2\")]\n    [Queue(\"jobs\")]\n    public void TestJob2(PerformContext context)\n    {\n        context.WriteLine($\"{DateTime.Now.ToString(\"yyyy/MM/dd HH:mm:ss\")} TestJob2 Running ...\");\n    }\n    [RecurringJob(\"*/2 * * * *\", \"China Standard Time\", \"jobs\")]\n    public void TestJob3(PerformContext context)\n    {\n        context.WriteLine($\"{DateTime.Now.ToString(\"yyyy/MM/dd HH:mm:ss\")} TestJob3 Running ...\");\n    }\n    [RecurringJob(\"*/5 * * * *\", \"jobs\")]\n    public void InstanceTestJob(PerformContext context)\n    {\n        context.WriteLine($\"{DateTime.Now.ToString(\"yyyy/MM/dd HH:mm:ss\")} InstanceTestJob Running ...\");\n    }\n\n    [RecurringJob(\"*/6 * * * *\", \"UTC\", \"jobs\")]\n    public static void StaticTestJob(PerformContext context)\n    {\n        context.WriteLine($\"{DateTime.Now.ToString(\"yyyy/MM/dd HH:mm:ss\")} StaticTestJob Running ...\");\n    }\n}\n```\n\n## Json Configuration\n\nIt is similar to [quartz.net](http://www.quartz-scheduler.net/), We also define the unified interface `IRecurringJob`.\nRecurring jobs must impl the specified interface like this.\n\n```csharp\n[AutomaticRetry(Attempts = 0)]\n[DisableConcurrentExecution(90)]\npublic class LongRunningJob : IRecurringJob\n{\n    public void Execute(PerformContext context)\n    {\n        context.WriteLine($\"{DateTime.Now.ToString(\"yyyy/MM/dd HH:mm:ss\")} LongRunningJob Running ...\");\n\n        var runningTimes = context.GetJobData\u003cint\u003e(\"RunningTimes\");\n\n        context.WriteLine($\"get job data parameter-\u003e RunningTimes: {runningTimes}\");\n\n        var progressBar = context.WriteProgressBar();\n\n        foreach (var i in Enumerable.Range(1, runningTimes).ToList().WithProgress(progressBar))\n        {\n            Thread.Sleep(1000);\n        }\n    }\n}\n```\n\nNow we need to provider the json config file to assign the implemented recurring job, the json configuration samples as below.\n\n```json\n[{\n    \"job-name\": \"My Job1\",\n    \"job-type\": \"Hangfire.Samples.MyJob1, Hangfire.Samples\",\n    \"cron-expression\": \"*/1 * * * *\",\n    \"timezone\": \"China Standard Time\",\n    \"queue\": \"jobs\"\n},\n{\n    \"job-name\": \"My Job2\",\n    \"job-type\": \"Hangfire.Samples.MyJob2, Hangfire.Samples\",\n    \"cron-expression\": \"*/5 * * * *\",\n    \"job-data\": {\n        \"IntVal\": 1,\n        \"StringVal\": \"abcdef\",\n        \"BooleanVal\": true,\n        \"SimpleObject\": {\n            \"Name\": \"Foo\",\n            \"Age\": 100\n        }\n    }\n},\n{\n    \"job-name\": \"Long Running Job\",\n    \"job-type\": \"Hangfire.Samples.LongRunningJob, Hangfire.Samples\",\n    \"cron-expression\": \"*/2 * * * *\",\n    \"job-data\": {\n        \"RunningTimes\": 300\n    }\n}]\n```\n\nThe json token description to the configuration is here.\n\nJSON Token | Description\n---|---\n**job-name** | *[required]* The job name to `RecurringJob`.\n**job-type** | *[required]* The job type while impl the interface `IRecurringJob`.\n**cron-expression** | *[required]* Cron expressions.\ntimezone | *[optional]* Default value is `TimeZoneInfo.Utc`.\nqueue | *[optional]* The specified queue name , default value is `default`.\njob-data | *[optional]* Similar to the [quartz.net](http://www.quartz-scheduler.net/) `JobDataMap`, it is can be deserialized to the type `Dictionary\u003cstring,object\u003e`.\nenable | *[optional]* Whether the `RecurringJob` can be added/updated, default value is true, if false `RecurringJob` will be deleted automatically.\n\n*To the json token `job-data`, we can use extension method to get/set data with specified key from storage which associated with `BackgroundJob.Id` when recurring job running.*\n\n```csharp\nvar intVal = context.GetJobData\u003cint\u003e(\"IntVal\");\n\ncontext.SetJobData(\"IntVal\", ++intVal);\n```\n\n## Building RecurringJob\n\n- Building with `CronJob`.\n\nIn hangfire client, we can use the helper class `CronJob` to add or update recurringjob automatically.\n\n```csharp\n//Builds within specified interface or class.\nCronJob.AddOrUpdate(typeof(RecurringJobService1),typeof(RecurringJobService2));\n\n//Builds by using multiple JSON configuration files.\nCronJob.AddOrUpdate(\"recurringjob1.json\",\"recurringjob2.json\");\n```\n\n- Building with `IGlobalConfiguration`.\n\nUse `IGlobalConfiguration` extension method `UseRecurringJob` to build `RecurringJob`, in .NET Core's Startup.cs.\n\n``` csharp\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddHangfire(x =\u003e\n    {\n        x.UseSqlServerStorage(_config.GetConnectionString(\"Hangfire\"));\n\n        x.UseConsole();\n\n        //using json config file to build RecurringJob automatically.\n        x.UseRecurringJob(\"recurringjob.json\");\n        //using RecurringJobAttribute to build RecurringJob automatically.\n        x.UseRecurringJob(typeof(RecurringJobService));\n\n        x.UseDefaultActivator();\n    });\n}\n```\n\n*For the json configuration file, we can monitor the file change and reload `RecurringJob` dynamically by passing the parameter `reloadOnChange = true`.*","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficsharp%2FHangfire.RecurringJobExtensions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ficsharp%2FHangfire.RecurringJobExtensions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficsharp%2FHangfire.RecurringJobExtensions/lists"}