Multi instance running for the same job in Hangfire

78 Views Asked by At

I have an asp.net core MVC 8 web app with hangfire (v1.8.7) configured that executes several jobs. Occasionally, a job may exceed the specified time and trigger another instance. My goal is to prevent Hangfire from launching multiple instances of the same job simultaneously.

I have only one server running

I tried to use the DisableConcurrentExecution attribute but it didn't work

[DisableConcurrentExecution(timeoutInSeconds: (3600))]
public ActionResult SetScheduledJob_SyncModifiedItemsFromAffiliateBox()
{
    RecurringJob.AddOrUpdate("SyncModifiedItemsFromAffiliateBox_OffHours", () => 
        SyncModifiedItemsFromAffiliateBoxJob(), Cron.Minutely());

    return RedirectToAction("index");
}

public void SyncModifiedItemsFromAffiliateBoxJob()
{
    Thread.Sleep(2 * 60 * 1000);
}

this is my program.cs code:

// Add Hangfire services.
builder.Services.AddHangfire(configuration => configuration
    .SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
    .UseSimpleAssemblyNameTypeSerializer()
    .UseRecommendedSerializerSettings()
    .UseSqlServerStorage(appSettings.GetConnectionString("HangfireConnection")));

// Add the processing server as IHostedService
builder.Services.AddHangfireServer();
app.UseHangfireDashboard();
app.MapHangfireDashboard();
1

There are 1 best solutions below

0
Akour Mohamed On

Here is the solution that works for me:

  • first, you need to create this class that gets registered jobs from the database and compares it with the ones running.

  • create class PreventConcurrentExecutionJobFilter:

    public class PreventConcurrentExecutionJobFilter : JobFilterAttribute, IClientFilter, IServerFilter { }

  • implements these methods on class:

      public void OnCreating(CreatingContext filterContext)
      {
          var jobs = JobStorage.Current.GetMonitoringApi().ProcessingJobs(0, 100);
    
          var methodAlreadyProcessing = jobs.Any(x => x.Value.Job.Method.Name == filterContext.Job.Method.Name);
    
          if (methodAlreadyProcessing)
          {
              filterContext.Canceled = true;
          }
      }
    
      public void OnPerformed(PerformedContext filterContext) { }
    
      void IClientFilter.OnCreated(CreatedContext filterContext) { }
    
      void IServerFilter.OnPerforming(PerformingContext filterContext) { }
    
  • second you need to call this class as attributes for the job method:

      [PreventConcurrentExecutionJobFilter]
      public void SyncModifiedItemsFromAffiliateBoxJob()
      {
          Thread.Sleep(2 * 60 * 1000);
      }