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!