Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hangfire single instance recurring job

I am trying to use Hangfire to run a recurring job in the background that polls data from another website, the issue is that I don't want the recurring job to run if the previous job is still running.

I've read through the documentation but can't seem to find the answer. Is there a way to have a recurring job that runs every 10 minutes but skips if the previous task is not done yet?

public void Configuration(IAppBuilder app)
{
    app.MapSignalR();

    // Hangfire
    GlobalConfiguration.Configuration
        .UseSqlServerStorage("DatabaseContext");

    app.UseHangfireDashboard();
    app.UseHangfireServer();

    RecurringJob.AddOrUpdate("site-parser", () => SiteParserService.RunAll(), Cron.Minutely, TimeZoneInfo.Utc);

    ConfigureAuth(app);
}
like image 761
devfunkd Avatar asked Jun 11 '15 17:06

devfunkd


People also ask

Where does Hangfire store recurring jobs?

Where does HangFire store recurring jobs? Persistent. Background jobs are created in a persistent storage – SQL Server and Redis supported officially, and a lot of other community-driven storages. You can safely restart your application and use Hangfire with ASP.NET without worrying about application pool recycles.

What Hangfire object and method is used to create a recurring job?

The call to AddOrUpdate method will create a new recurring job or update existing job with the same identifier.

What are Hangfire jobs?

Hangfire is an open-source framework that can be used to perform background processing in . Net and . Net Core applications. It is mainly used to perform background tasks such as batch/email notification, batch import of files, video/image processing, database maintaining, file purging, etc.

How do I know if my Hangfire job is running?

If you have a job that takes some time and is currently processing/running, in the Hangfire dashboard page, select the “Jobs” item in the top navigation bar. This shows entries for Enqueued, Scheduled, Processing, etc. Click the “Processing” entry, and you should see your currently processing job (or jobs).


2 Answers

You can use; [DisableConcurrentExecution(10 * 60)] attribute on the job method.

Here you can find information about this attribute: http://odinserj.net/2014/05/21/hangfire-0.8.2-released/

like image 124
tozlu Avatar answered Sep 21 '22 13:09

tozlu


My solution:

namespace MyNameSpace
{
    public delegate void LockWrapperDelegateVoid();

    /* Job Locker. One job can work at current moment. Different jobs can work parallel */
    public static class JobLocker
    {
        private static readonly ConcurrentDictionary<string, bool> _locks = new ConcurrentDictionary<string, bool>();

        private static string LocksTryAdd(string lockerName)
        {
            if (string.IsNullOrEmpty(lockerName))  // lock by procedure's name (in this example = "JobProcedure")
            {
                lockerName = new StackFrame(2).GetMethod().Name;
            }
            if (!_locks.ContainsKey(lockerName))
            {
                _locks.TryAdd(lockerName, false);
            }
            return lockerName;
        }

        public static void LockWrapperVoid(string lockerName, LockWrapperDelegateVoid lockWrapperDelegateVoid)
        {
            lockerName = LocksTryAdd(lockerName);
            if (!_locks[lockerName])
            {
                _locks[lockerName] = true;
                try
                {
                    lockWrapperDelegateVoid();
                }
                finally
                {
                    _locks[lockerName] = false;
                }
            }
        }
    }
}

// USING

// JOB description
TryAddOrUpdateJob("JOB TITLE", () => JobManager.JobProcedure(), "* * * * *", TimeZoneInfo.Utc, "queueDefault");  // every one minute


public static void JobProcedure()
{
    // very important. You can use "BlockArea" instead null and use one area if several jobs depend each other
    // if null - area will have name like as the procedure ("JobProcedure")
    JobLocker.LockWrapperVoid(null, () =>  
    {
        //your code here
        System.Threading.Thread.Sleep(2 * 1000 * 60); // timeout - 2 minutes
    });
}
like image 42
Pavel Samoylenko Avatar answered Sep 20 '22 13:09

Pavel Samoylenko