Specify Hangfire Queue in BackgroundJob Calling Method


#1

Is there a way to specify the name of the queue when calling the method and not having to add an attribute to the method? I have a legacy class library that is compiled against .NET 3.5 and cannot update to .NET 4.5 to install Hangfire.Core in order to add the attribute [Queue("critical")] to the call of the method.

I have 2 queues, 1 that is “critical” and one that is “default”. I want this one method to always use this specific queue to process.

Is there a way to specify the queue in this way? If not, can it be added to handle this situation?

var processor = new MyClassInDotNet35();
BackgroundJob.Enqueue(() => processor.Run(DateTime.UtcNow), "critical");

I want to enqueue a job to all server attached to Hangfire
#2

Yep, Hangfire itself is a disguised state machine, you can specify the queue at runtime in the following way:

using Hangfire;
using Hangfire.States;

var client = new BackgroundJobClient();
var state = new EnqueuedState("your-queue");

client.Create(() => Console.WriteLine("Hi!"), state);

#3

Thank you, I couldn’t find this anywhere in the documentation.

What about scheduling a job to run on a specific queue? I don’t see an overload to include the EnqueuedState object.


#4

Yep, a lot of things aren’t documented yet. There is no possibility to use another queue for scheduled jobs so far, but you can simply write a wrapper method:

// Old method
BackgroundJob.Enqueue(() => Console.WriteLine("Old"))

// New method
[Queue("critical")]
public static void CustomWriteLine(string value) 
{ 
    Console.WriteLine(value);
}

BackgroundJob.Enqueue(() => CustomWriteLine("New"));

#5

@odinserj

I have a shared hangfire database, one application queues job in default queue, others have their specific queues.
If I use BankgroundJob.Enqueue it respects queue and assigns accordingly. However when I use BackgroundJob.Schedule in a specific queue, it is being picked by any of all executors irrespective of queue name.

The version I am using is 1.6.9. Please suggest any workaround.

Thank you
Najam


#6

Hi!

What if my queue name is dynamic? It would be hard (if not impossible) to dynamically add an attribute to my wrapper method.

Is there another way to Schedule a job to a specific queue?

Thank you.


#7

What I ended up doing was I schedule I job to enqueue job on a specific queue. It’s not ideal, but it’s been working.

So I do something like

BackgroundJob.Schedule(() => ForceTheQForWhateverJob(info), TimeSpan.FromMonutes(30));

then that method just does:

void ForceTheQForWhateverJob(object info) {
    var client = new BackgroundJobClient();
    client.Create(DoSomethingWithMyParmeters(info), new EnqueuedState("QUEUE_NAME"));
}

#8

I managed to queue and schedule a job in a specific queue by adding a custom filter provider. I can choose in which queue to get it executed based on the Job data.

JobFilterProviders.Providers.Add(new CustomJobFilterProvider());

public class  CustomJobFilterProvider: IJobFilterProvider
{
    public IEnumerable<JobFilter> GetFilters(Job job)
    {
        String queueName = GetQueueName(job);
        return new JobFilter[]
        {
            new JobFilter(

                new QueueAttribute(queueName),
                JobFilterScope.Method, null
            )
        };
    }

    String GetQueueName(Job job)
    {
        return "myqueue";
    }
}

#9

Great solution. Worked a treat for me!


#10

Hi All,
Another workaround for this problem is:

var options = new BackgroundJobServerOptions
{
Queues = new[] { “**UNIQUE JOB NAME for JOB 1”, “default” , “**UNIQUE JOB NAME for JOB 2”, “xyz”} // Add as many jobs as you want - just follow the sample and then add it in the JSON file
};
appBuilder.UseHangfireServer(options);
GlobalConfiguration.Configuration.UseRecurringJob(".json");
GlobalConfiguration.Configuration.UseDefaultActivator();
/////////////////////////////////////////////////
My JSON file is:

[
{
“job-name”: “NAME 2”,
“job-type”: “PROGRAM.CLASSNAME1, PROGRAM”,
// “cron-expression”: “*/5 * * * *”,
“cron-expression”: “5 10 * * fri”,
//“cron-expression”: “5 6 * * mon”,
“timezone”: “YOUR TIME ZONE”,
“queue”: “**UNIQUE JOB NAME for JOB 1
},
{
“job-name”: “NAME 2”,
“job-type”: “PROGRAM.CLASSNAME2, PROGRAM”,
“cron-expression”: “5 11 * * fri”,
//“cron-expression”: “15 6 * * mon”,
“timezone”: “YOUR TIME ZONE”,
“queue”: “**UNIQUE JOB NAME for JOB 2
}
]