Extensions for Hangfire to build RecurringJob automatically
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.vscode
samples/Hangfire.Samples
src/Hangfire.RecurringJobExtensions
test/Hangfire.RecurringJobExtensions.Tests upgrade vs version and add unit test Feb 7, 2018
.gitattributes
.gitignore
Hangfire.RecurringJobExtensions.sln
LICENSE
README.md
appveyor.yml

README.md

Hangfire.RecurringJobExtensions

Official Site NuGet Build status License MIT

This repo is the extension for Hangfire to build RecurringJob automatically. When app start, RecurringJob will be added/updated automatically. There is two ways to build RecurringJob.

  • RecurringJobAttribute attribute
  • Json Configuration

Using RecurringJobAttribute

We can use the attribute RecurringJobAttribute to assign the interface/instance/static method.

public class RecurringJobService
{
    [RecurringJob("*/1 * * * *")]
    [Queue("jobs")]
    public void TestJob1(PerformContext context)
    {
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} TestJob1 Running ...");
    }
    [RecurringJob("*/2 * * * *", RecurringJobId = "TestJob2")]
    [Queue("jobs")]
    public void TestJob2(PerformContext context)
    {
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} TestJob2 Running ...");
    }
    [RecurringJob("*/2 * * * *", "China Standard Time", "jobs")]
    public void TestJob3(PerformContext context)
    {
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} TestJob3 Running ...");
    }
    [RecurringJob("*/5 * * * *", "jobs")]
    public void InstanceTestJob(PerformContext context)
    {
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} InstanceTestJob Running ...");
    }

    [RecurringJob("*/6 * * * *", "UTC", "jobs")]
    public static void StaticTestJob(PerformContext context)
    {
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} StaticTestJob Running ...");
    }
}

Json Configuration

It is similar to quartz.net, We also define the unified interface IRecurringJob. Recurring jobs must impl the specified interface like this.

[AutomaticRetry(Attempts = 0)]
[DisableConcurrentExecution(90)]
public class LongRunningJob : IRecurringJob
{
    public void Execute(PerformContext context)
    {
        context.WriteLine($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")} LongRunningJob Running ...");

        var runningTimes = context.GetJobData<int>("RunningTimes");

        context.WriteLine($"get job data parameter-> RunningTimes: {runningTimes}");

        var progressBar = context.WriteProgressBar();

        foreach (var i in Enumerable.Range(1, runningTimes).ToList().WithProgress(progressBar))
        {
            Thread.Sleep(1000);
        }
    }
}

Now we need to provider the json config file to assign the implemented recurring job, the json configuration samples as below.

[{
    "job-name": "My Job1",
    "job-type": "Hangfire.Samples.MyJob1, Hangfire.Samples",
    "cron-expression": "*/1 * * * *",
    "timezone": "China Standard Time",
    "queue": "jobs"
},
{
    "job-name": "My Job2",
    "job-type": "Hangfire.Samples.MyJob2, Hangfire.Samples",
    "cron-expression": "*/5 * * * *",
    "job-data": {
        "IntVal": 1,
        "StringVal": "abcdef",
        "BooleanVal": true,
        "SimpleObject": {
            "Name": "Foo",
            "Age": 100
        }
    }
},
{
    "job-name": "Long Running Job",
    "job-type": "Hangfire.Samples.LongRunningJob, Hangfire.Samples",
    "cron-expression": "*/2 * * * *",
    "job-data": {
        "RunningTimes": 300
    }
}]

The json token description to the configuration is here.

JSON Token Description
job-name [required] The job name to RecurringJob.
job-type [required] The job type while impl the interface IRecurringJob.
cron-expression [required] Cron expressions.
timezone [optional] Default value is TimeZoneInfo.Utc.
queue [optional] The specified queue name , default value is default.
job-data [optional] Similar to the quartz.net JobDataMap, it is can be deserialized to the type Dictionary<string,object>.
enable [optional] Whether the RecurringJob can be added/updated, default value is true, if false RecurringJob will be deleted automatically.

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.

var intVal = context.GetJobData<int>("IntVal");

context.SetJobData("IntVal", ++intVal);

Building RecurringJob

  • Building with CronJob.

In hangfire client, we can use the helper class CronJob to add or update recurringjob automatically.

//Builds within specified interface or class.
CronJob.AddOrUpdate(typeof(RecurringJobService1),typeof(RecurringJobService2));

//Builds by using multiple JSON configuration files.
CronJob.AddOrUpdate("recurringjob1.json","recurringjob2.json");
  • Building with IGlobalConfiguration.

Use IGlobalConfiguration extension method UseRecurringJob to build RecurringJob, in .NET Core's Startup.cs.

public void ConfigureServices(IServiceCollection services)
{
    services.AddHangfire(x =>
    {
        x.UseSqlServerStorage(_config.GetConnectionString("Hangfire"));

        x.UseConsole();

        //using json config file to build RecurringJob automatically.
        x.UseRecurringJob("recurringjob.json");
        //using RecurringJobAttribute to build RecurringJob automatically.
        x.UseRecurringJob(typeof(RecurringJobService));

        x.UseDefaultActivator();
    });
}

For the json configuration file, we can monitor the file change and reload RecurringJob dynamically by passing the parameter reloadOnChange = true.