I have a couple instances of Hangfire running on two servers using the same database. Each instance submits jobs to be run based on some criteria based on server name so that no two instances run the same job. I noticed that they are running the same jobs which means when an instance is running it's picking any job in the queue in the database regardless if it submitted the job or not. I thought in the latest version 1.6.x, each job is unique. It seems this doesn't mean it runs only on the instance that created it?
How do I get each instance to run jobs it submitted only?
Hangfire handles different types of background jobs, and all of them are invoked in a separate execution context. Fire and forget jobs are executed once on an immediate basis after creation. Once you create a fire-and-forget job, it is saved to its queue ("default" by default, but multiple queues supported).
You can remove an existing recurring job by calling the RemoveIfExists method. It does not throw an exception when there is no such recurring job.
Hangfire is an open-source and well-documented task scheduler for ASP.NET and ASP.NET Core. It's multi-threaded, easily scalable, and offers a variety of job types.
Hangfire Server consists of different components that are doing different work: workers listen to queue and process jobs, recurring scheduler enqueues recurring jobs, schedule poller enqueues delayed jobs, expire manager removes obsolete jobs and keeps the storage as clean as possible, etc.
You need to use queues to select which server handles specific jobs.
The idea is to categorize jobs by specifying a queue. Then for each server you will specify which queue(s) they watch.
The only problem with this, in my opinion, is that choosing the queue for a job is not straightforward (unless you are working with RecurringJobs).
When you start the Hangfire instance for a server, use the Queues
BackgroundJobServerOptions
as per the documentation:
app.UseHangfireServer(new BackgroundJobServerOptions()
{
// order defines priority
// beware that queue names should be lowercase only
Queues = new [] { "critical", "default", "myqueueformyserver" }
});
There are two cases:
RecurringJobs: RecurringJob.AddOrUpdate("MyFirstRecurringJob", () => myClass.myMethod(), Cron.Minutely(), null, "myqueueformyserver");
BackgroundJobs: you cannot specify the queue for the job at enqueue time (Hangfire.BackgroundJob.Enqueue(() => myClass.myMethod());
) there is no option for this. The solution is to use a method or class attribute. Hangfire provides a QueueAttribute
:[Queue("myqueueformyserver")]
public void myMethod() { }
If I understand your requirements, the static QueueAttribute
will not fit you as you want to dynamically assign the queue. I had the same situation and created my own attribute inspired by the code of the QueueAttribute.
It looks something like that (adapt to your willing/needs)
public class MyQueueAttribute : JobFilterAttribute, IElectStateFilter
{
public MyQueueAttribute(string paramQueue)
{
ParamQueue = paramQueue;
}
public string ParamQueue { get; }
public void OnStateElection(ElectStateContext context)
{
var enqueuedState = context.CandidateState as EnqueuedState;
if (enqueuedState != null)
{
enqueuedState.Queue = string.Concat(Environment.MachineName.ToLower(),
ParamQueue);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With