Stop Hangfire job from enqueuing if already enqueued
Asked Answered
N

2

10

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

Nasty answered 13/6, 2016 at 14:9 Comment(2)
Another option is the DisableConcurrentExecution attribute. It has a required timeoutInSeconds argument.Infrastructure
That would just make them process one at a time and not really what I'm trying to achieve.Nasty
C
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());

Catafalque answered 20/3, 2018 at 15:26 Comment(1)
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.Tice
X
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
Xenogenesis answered 2/10, 2016 at 19:19 Comment(2)
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!Nasty
How do I get the YOURJOBNAME when I am calling IsOKToAddJob?Interoceptor

© 2022 - 2024 — McMap. All rights reserved.