This documentation says that you can specify a queue by using the Queue
attribute on the method to be invoked. This assumes that you always want execute a method on the same queue. Is there a way for the process that calls Enqueue
to specify the name of the queue to put the job into (effectively putting the decision-making in the hands of the job generator, not the definition of the job).
With a instance of IBackgroundJobClient you can specify a queue.
IBackgroundJobClient hangFireClient = new BackgroundJobClient();
EnqueuedState myQueueState = new Hangfire.States.EnqueuedState("myQueue");
hangFireClient.Create<SomeClass>(c => c.SomeMethod(), myQueueState);
Note that in this way, a retry will put the job back to the default queue. You will require additional code to retry in the same queue, using a JobFilter
http://discuss.hangfire.io/t/one-queue-for-the-whole-farm-and-one-queue-by-server/490/3
If you want to change the queue Dynamically you can follow this way.
This implementation works for all Enqueue
, Schedule
and ContinueJobWith
Version 1.7.X onwords
public class HangfireDynamicQueue
{
public void EnqueJobs()
{
// Enqueue "MyBackgroundJob1" under "default" queue
var job1 = BackgroundJob.Enqueue("default",() => MyBackgroundJob1(123));
// Enqueue "MyBackgroundJob1" under "critical" queue
var job2 = BackgroundJob.Enqueue("critical", () => MyBackgroundJob1(345));
// Execute "MyBackgroundJob1" after 10 seconds under "delayed" queue
var job3 = BackgroundJob.Schedule("delayed", () => MyBackgroundJob1(567), TimeSpan.FromSeconds(10));
// Run "MyBackgroundJob2" after job3 under "continue" queue
var job4 = BackgroundJob.ContinueJobWith(job3, "continue", () => MyBackgroundJob2(789));
}
public void MyBackgroundJob1( int arg)
{
// Job implementation
}
public void MyBackgroundJob2(int arg)
{
// Job implementation
}
}
Before version 1.7.X - Outdated
This implementation works for all Enqueue
, Schedule
and ContinueJobWith
The trick happen on [Queue("{0}")]
. Hangfire will pass job arguments to the given pattern ("{0}"
) using String.Format("{0}", job.Args)
to get the actual queue on every state change, so the target queue will be applied even for retries.
Highlighted Code Syntax :
// Enqueue "MyBackgroundJob1" under "critical" queue
var job2 = BackgroundJob.Enqueue(() => MyBackgroundJob1("critical", 523));
// Use one of following Attributes depending on your hangfire version
//[AdvancedQueue("{0}")] // 1.6.X
[Queue("{0}")] // In 1.7.X
public void MyBackgroundJob1(string queueName, int arg)
{
// Job implementation
}
Full Implementation :
public class HangfireDynamicQueue
{
public void EnqueJobs()
{
// Enqueue "MyBackgroundJob1" under "default" queue
var job1 = BackgroundJob.Enqueue(() => MyBackgroundJob1("default", 123));
// Enqueue "MyBackgroundJob1" under "critical" queue
var job2 = BackgroundJob.Enqueue(() => MyBackgroundJob1("critical", 523));
// Execute "MyBackgroundJob1" after 10 seconds under "delayed" queue
var job3 = BackgroundJob.Schedule(() => MyBackgroundJob1("delayed", 678), TimeSpan.FromSeconds(10));
// Run "MyBackgroundJob2" after job3 under "delayed" queue
var job4 = BackgroundJob.ContinueJobWith(job3, () => MyBackgroundJob2("delayed", 435));
}
// Use one of following Attributes depending on your hangfire version
//[AdvancedQueue("{0}")] // 1.6.X
[Queue("{0}")] // In 1.7.X
public void MyBackgroundJob1(string queueName, int arg)
{
// Job implementation
}
// Use one of following Attributes depending on your hangfire version
//[AdvancedQueue("{0}")] // 1.6.X
[Queue("{0}")] // In 1.7.X
public void MyBackgroundJob2(string queueName, int arg)
{
// Job implementation
}
}
Since adding an extra parameter seems to be so hard for the Hangfire team ;-)....
...I've found the most convenient way is to make two methods that just call the actual implementation, and put different [Queue]
attributes on each.
Usually if I need to switch queues it's between dev / production and I want to just call something like RunOrder(...)
with isTestOrder=boolean
and not be concerned about queues at that level.
public void RunOrder(int orderId, bool isTestOrder)
{
if (isTestOrder)
{
BackgroundJob.Enqueue(() => _RunTestOrder(orderId));
}
else
{
BackgroundJob.Enqueue(() => _RunOrder(orderId));
}
}
[Queue("dev")]
public void _RunTestOrder(int orderId) {
OrderProcessor.RunOrder(orderId); // actual code to call processor
}
[Queue("production")]`
public void _RunProductionOrder(int orderId) {
OrderProcessor.RunOrder(orderId); // is the same in both 'hangfire proxies'
}
Note usage of _
to indicate these aren't meant to be called directly. I don't remember off hand if hangfire methods need to be public or not - but if they do need to be then the _
is more important.
© 2022 - 2024 — McMap. All rights reserved.