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).
Server Configuration
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" }
});
Selecting a queue for a job
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);
}
}
}