9

Is there a simple way of stopping a hangfire.io job from enqueuing if one is already enqueued?

Looking at the jobfilterattribute, nothing stands out as how to get the state of anything on the server. Can I use the connection objects and query the store?

Thanks

William
  • 1,375
  • 12
  • 27

2 Answers2

5

Have a look at the following gist by the library owner https://gist.github.com/odinserj/a8332a3f486773baa009

This should prevent the same job from being en-queued more than once by querying the fingerprint.

You can activate it per background job by decorating the method with the attribute [DisableMultipleQueuedItemsFilter].

Or you can enable it globally GlobalJobFilters.Filters.Add(new DisableMultipleQueuedItemsFilter());

tjackadams
  • 815
  • 2
  • 9
  • 26
  • 2
    Does this solution still works in latest Hangire 1.7.8? Is this solution bullet proof & does it somehow affect performance? We do a LOT of jobs via Hangfire. – sabiland Jan 10 '20 at 06:37
0

I am using following code block to check to add new job or not, depending on its current state: (I know that i am currently looking at only first 1000 jobs. You can implement your type of logic))

private static bool IsOKToAddJob(string JobName, string QueueName, out string NotOKKey)
    {
        try
        {
            var monapi = JobStorage.Current.GetMonitoringApi();
            var processingJobs = monapi.ProcessingJobs(0, 1000);
            NotOKKey = processingJobs.Where(j => j.Value.Job.ToString() == JobName).FirstOrDefault().Key;

            if (!string.IsNullOrEmpty(NotOKKey)) return false;

            var scheduledJobs = monapi.ScheduledJobs(0, 1000);
            NotOKKey = scheduledJobs.Where(j => j.Value.Job.ToString() == JobName).FirstOrDefault().Key;

            if (!string.IsNullOrEmpty(NotOKKey)) return false;

            var enqueuedJobs = monapi.EnqueuedJobs(QueueName, 0, 1000);
            NotOKKey = enqueuedJobs.Where(j => j.Value.Job.ToString() == JobName).FirstOrDefault().Key;

            if (!string.IsNullOrEmpty(NotOKKey)) return false;

            NotOKKey = null;
            return true;
        }
        catch (Exception ex)
        {
            //LOG your Exception;
        }
    }

And the usage is simple:

if (IsOKToAddJob(YOURJOBNAME, QueueName, out NOTOKKey))
    var id = BackgroundJob.Enqueue(() =>YOURMETHOD()); 

//rest
Onur Omer
  • 506
  • 3
  • 12
  • Interesting solution, but because the way i have to enqueue in a tight transaction, i don't want to query in the clients. Maybe I can do that in the attribute. Thanks! – William Oct 04 '16 at 13:53
  • How do I get the `YOURJOBNAME` when I am calling `IsOKToAddJob`? – software_writer Dec 14 '16 at 20:46