Skip to content

Commit

Permalink
Merge pull request #18 from anthonypos/master
Browse files Browse the repository at this point in the history
IRecurringJobManager updates
  • Loading branch information
maitlandmarshall authored Apr 8, 2022
2 parents 0e7e5fd + 2bc3250 commit 4ec3185
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 17 deletions.
3 changes: 2 additions & 1 deletion MIFCore.Hangfire/HangfireServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ public static IServiceCollection AddHangfire(this IServiceCollection serviceDesc
Globals.DefaultConfiguration.Bind(hangfireConfig);
serviceDescriptors.AddSingleton(hangfireConfig);

serviceDescriptors.AddHangfire(configuration: cfg => configureDelegate?.Invoke(cfg, hangfireConfig));
serviceDescriptors.AddHangfire(configuration: cfg => configureDelegate?.Invoke(cfg, hangfireConfig));
serviceDescriptors.AddTransient<JobStorageFactory>();
serviceDescriptors.AddTransient<IRecurringJobManager, MIFCoreRecurringJobManager>();

return serviceDescriptors;
}
Expand Down
1 change: 1 addition & 0 deletions MIFCore.Hangfire/IRecurringJobFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace MIFCore.Hangfire
{
[Obsolete("IRecurringJobFactory is obsolete. Please use Hangfire.IRecurringJobManager.")]
public interface IRecurringJobFactory
{
void CreateRecurringJob(string jobName, Expression<Func<Task>> methodCall, string cronSchedule = null, string queue = "default", bool triggerIfNeverExecuted = false);
Expand Down
30 changes: 30 additions & 0 deletions MIFCore.Hangfire/IRecurringJobManagerExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Hangfire;
using System;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace MIFCore.Hangfire
{
public static class IRecurringJobManagerExtensions
{
public static void CreateRecurringJob(this IRecurringJobManager recurringJobManager, string jobName, Expression<Func<Task>> methodCall, string cronSchedule = null, string queue = "default", bool triggerIfNeverExecuted = false)
{
var manager = recurringJobManager as MIFCoreRecurringJobManager;

if (manager is null)
throw new ArgumentException("Parameter 'recurringJobManager' is not of type 'MIFCore.Hangfire.MIFCoreRecurringJobManager'");

manager.CreateRecurringJob(jobName: jobName, methodCall: methodCall, cronSchedule: cronSchedule, queue: queue, triggerIfNeverExecuted: triggerIfNeverExecuted);
}

public static void CreateRecurringJob<T>(this IRecurringJobManager recurringJobManager, string jobName, Expression<Func<T, Task>> methodCall, string cronSchedule = null, string queue = "default", bool triggerIfNeverExecuted = false)
{
var manager = recurringJobManager as MIFCoreRecurringJobManager;

if (manager is null)
throw new ArgumentException("Parameter 'recurringJobManager' is not of type 'MIFCore.Hangfire.MIFCoreRecurringJobManager'");

manager.CreateRecurringJob<T>(jobName: jobName, methodCall: methodCall, cronSchedule: cronSchedule, queue: queue, triggerIfNeverExecuted: triggerIfNeverExecuted);
}
}
}
4 changes: 2 additions & 2 deletions MIFCore.Hangfire/MIFCore.Hangfire.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
<Description>The Hangfire add-on for MIFCore.</Description>

<Major>1</Major>
<Minor>0</Minor>
<Build>2</Build>
<Minor>1</Minor>
<Build>0</Build>
<Revision>0</Revision>

<Version>$(Major).$(Minor).$(Build).$(Revision)</Version>
Expand Down
104 changes: 104 additions & 0 deletions MIFCore.Hangfire/MIFCoreRecurringJobManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
using Hangfire;
using Hangfire.Annotations;
using Hangfire.Common;
using Hangfire.Storage;
using Microsoft.Extensions.Configuration;
using MIFCore.Common;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace MIFCore.Hangfire
{
public class MIFCoreRecurringJobManager : IRecurringJobManager
{
private readonly IRecurringJobManager recurringJobManager;
private readonly JobStorage jobStorage;

public MIFCoreRecurringJobManager(JobStorage jobStorage)
{
this.recurringJobManager = new RecurringJobManager(jobStorage);
this.jobStorage = jobStorage;
}

public void CreateRecurringJob<T>(string jobName, Expression<Func<T, Task>> methodCall, string cronSchedule = null, string queue = "default", bool triggerIfNeverExecuted = false)
{
cronSchedule = this.GetCronSchedule(jobName, cronSchedule);

var job = Job.FromExpression(methodCall);

this.recurringJobManager.AddOrUpdate<T>(
recurringJobId: jobName,
methodCall: methodCall,
cronExpression: cronSchedule,
timeZone: TimeZoneInfo.Local,
queue: queue);

if (triggerIfNeverExecuted)
this.TriggerRecurringJobIfNeverExecuted(jobName);
}

public void CreateRecurringJob(string jobName, Expression<Func<Task>> methodCall, string cronSchedule = null, string queue = "default", bool triggerIfNeverExecuted = false)
{
cronSchedule = this.GetCronSchedule(jobName, cronSchedule);

this.recurringJobManager.AddOrUpdate(
recurringJobId: jobName,
methodCall: methodCall,
cronExpression: cronSchedule,
timeZone: TimeZoneInfo.Local,
queue: queue);

if (triggerIfNeverExecuted)
this.TriggerRecurringJobIfNeverExecuted(jobName);
}

public string GetCronSchedule(string jobName, string cronSchedule = null)
{
// override if jobName is available in the settings file.
var cronOverride = this.GetCronFromConfig(jobName);

if (string.IsNullOrWhiteSpace(cronOverride))
{
return cronSchedule ?? Cron.Daily();
}
else
{
return cronOverride;
}
}

private string GetCronFromConfig(string jobName)
{
var section = Globals.DefaultConfiguration.GetSection(jobName);
return section.Exists() ? section.Value : null;
}

private void TriggerRecurringJobIfNeverExecuted(string jobName)
{
var connection = this.jobStorage.GetConnection();
var newJob = connection.GetRecurringJobs(new string[] { jobName }).First();

if (newJob.LastExecution is null)
RecurringJob.Trigger(jobName);
}

public void RemoveIfExists([NotNull] string recurringJobId)
{
RecurringJob.RemoveIfExists(recurringJobId);
}

public void Trigger([NotNull] string recurringJobId)
{
RecurringJob.Trigger(recurringJobId);
}

public void AddOrUpdate([NotNull] string recurringJobId, [NotNull] Job job, [NotNull] string cronExpression, [NotNull] RecurringJobOptions options)
{
cronExpression = GetCronSchedule(recurringJobId, cronExpression);

this.recurringJobManager.AddOrUpdate(recurringJobId: recurringJobId, job: job, cronExpression: cronExpression, options: options);
}
}
}
3 changes: 2 additions & 1 deletion MIFCore.Hangfire/RecurringJobFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace MIFCore.Hangfire
{
[Obsolete("RecurringJobFactory is obsolete. Please use MIFCore.Hangfire.MIFCoreRecurringJobManager.")]
public class RecurringJobFactory : IRecurringJobFactory
{
private readonly IRecurringJobManager recurringJobManager;
Expand All @@ -22,7 +23,7 @@ public RecurringJobFactory(IRecurringJobManager recurringJobManager, JobStorage

public void CreateRecurringJob<T>(string jobName, Expression<Func<T, Task>> methodCall, string cronSchedule = null, string queue = "default", bool triggerIfNeverExecuted = false)
{
cronSchedule = this.GetCronSchedule(jobName, cronSchedule);
cronSchedule = this.GetCronSchedule(jobName, cronSchedule);

this.recurringJobManager.AddOrUpdate<T>(
recurringJobId: jobName,
Expand Down
8 changes: 6 additions & 2 deletions MIFCore.TestApp/SomeJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,21 @@ public SomeJob(IBackgroundJobClient backgroundJobClient)

[JobDisplayName("dogJob")]
[DisableConcurrentExecution(1000)]
public void DoTheJob()
public Task DoTheJob()
{
var current = BackgroundJobContext.Current;

Console.WriteLine("yees");
this.backgroundJobClient.Enqueue<SomeJob>(y => y.DoTheNextJob());

return Task.CompletedTask;
}

public void TriggeredJobAction()
public Task TriggeredJobAction()
{
Console.WriteLine("triggered job action");

return Task.CompletedTask;
}

public async Task DoTheNextJob()
Expand Down
4 changes: 2 additions & 2 deletions MIFCore.TestApp/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public void Configure()

public void PostConfigure(IBackgroundJobClient backgroundJobClient, IRecurringJobManager recurringJobManager)
{
recurringJobManager.AddOrUpdate<SomeJob>("some-job", y => y.DoTheJob(), Cron.Monthly());
recurringJobManager.AddOrUpdate<SomeJob>("some-job-triggered", y => y.TriggeredJobAction(), Cron.Monthly());
recurringJobManager.CreateRecurringJob<SomeJob>("some-job", y => y.DoTheJob(), Cron.Monthly());
recurringJobManager.CreateRecurringJob<SomeJob>("some-job-triggered", y => y.TriggeredJobAction(), Cron.Monthly());

backgroundJobClient.Enqueue<SomeJob>(y => y.DoTheJob());
backgroundJobClient.Enqueue<SomeJob>(y => y.DoTheJobButError());
Expand Down
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ public void Configure(IGlobalConfiguration hangfireGlobalConfig, MyConfig myConf
The `PostConfigure` method is executed after the above methods have finished and the `IHost.Run()` method has been called. This method can be used for running any other startup functionality required e.g. running migrations for your DbContext, registering your recurring Hangfire jobs or executing a job immediately:

```csharp
public void PostConfigure(MyDbContext myDbContext, MyConfig myConfig, IRecurringJobFactory recurringJobFactory)
public void PostConfigure(MyDbContext myDbContext, MyConfig myConfig, IRecurringJobManager recurringJobManager)
{
myDbContext.Database.Migrate();

recurringJobFactory.CreateRecurringJob<MyRecurringJob>("MyJobName", y => y.RunMyJob(), Cron.Daily(), myConfig.MyQueueName);
recurringJobManager.CreateRecurringJob<MyRecurringJob>("MyJobName", y => y.RunMyJob(), Cron.Daily(), myConfig.MyQueueName);
}
```

Expand Down Expand Up @@ -249,10 +249,10 @@ If the `Database` column is left as a null value, MIFCore will use the current d
To create some Job Actions, register your required recurring jobs in the application startup class:

```csharp
public void PostConfigure(IRecurringJobFactory recurringJobFactory)
public void PostConfigure(IRecurringJobManager recurringJobManager)
{
recurringJobFactory.CreateRecurringJob<MyRecurringJob>("MyJob", y => y.RunMyJob(), Cron.Daily());
recurringJobFactory.CreateRecurringJob<MyRecurringJob>("MyOtherJob", y => y.RunMyOtherJob(), Cron.Daily());
recurringJobManager.CreateRecurringJob<MyRecurringJob>("MyJob", y => y.RunMyJob(), Cron.Daily());
recurringJobManager.CreateRecurringJob<MyRecurringJob>("MyOtherJob", y => y.RunMyOtherJob(), Cron.Daily());
}
```

Expand Down Expand Up @@ -292,18 +292,20 @@ GO

The `recurring-job:` prefix is required on the action in order to execute an existing recurring job. The format of the action should be `recurring-job:{RecurringJobName}`. By default, Job Actions will be executed against the database configured in the `ConnectionString` property of the `settings.json` file.

### Recurring Job Factory
### Recurring Jobs

The `IRecurringJobFactory` class should be used when registering your recurring jobs in MIFCore. When a new job is registered, the `IRecurringJobFactory` will check for any CRON overrides specifies in the `settings.json` and create or update your job in Hangfire.
NOTE: `IRecurringJobFactory & RecurringJobFactory are now obsolete in MIFCore.Hangfire v1.1.0`

The `Hangfire.IRecurringJobManager` interface should be used when registering your recurring jobs in MIFCore. When a new job is registered, the `IRecurringJobManager` will check for any CRON overrides specified in the `settings.json` and create or update your job in Hangfire.

```csharp
recurringJobFactory.CreateRecurringJob<MyRecurringJob>("MyJobName", y => y.RunMyJob(), Cron.Daily());
recurringJobManager.CreateRecurringJob<MyRecurringJob>("MyJobName", y => y.RunMyJob(), Cron.Daily());
```

Set the `triggerIfNeverExecuted` parameter to true if you need Hangfire to trigger the job if it has not been run previously:

```csharp
recurringJobFactory.CreateRecurringJob<MyRecurringJob>("MyJobName", y => y.RunMyJob(), Cron.Daily(), triggerIfNeverExecuted: true);
recurringJobManager.CreateRecurringJob<MyRecurringJob>("MyJobName", y => y.RunMyJob(), Cron.Daily(), triggerIfNeverExecuted: true);
```

#### Overriding Recurring Job Schedules
Expand Down

0 comments on commit 4ec3185

Please sign in to comment.