在 HangFire 中,我可以使用队列名称入队而不是使用队列属性吗?

In HangFire, can I Enqueue with a queue name instead of using the Queue attribute?

这个documentation说你可以通过在要调用的方法上使用Queue属性来指定一个队列。这假设您总是希望在同一个队列上执行一个方法。有没有办法让调用 Enqueue 的进程指定将作业放入的队列名称(有效地将决策权交给作业生成器,而不是作业的定义)。

使用 IBackgroundJobClient 的实例,您可以指定一个队列。

IBackgroundJobClient hangFireClient = new BackgroundJobClient();
EnqueuedState myQueueState = new Hangfire.States.EnqueuedState("myQueue");
hangFireClient.Create<SomeClass>(c => c.SomeMethod(), myQueueState);

请注意,通过这种方式,重试会将作业放回默认队列。您将需要使用 JobFilter

在同一队列中重试其他代码

http://discuss.hangfire.io/t/one-queue-for-the-whole-farm-and-one-queue-by-server/490/3

因为添加一个额外的参数对 Hangfire 团队来说似乎很难 ;-).....

...我发现最方便的方法是制作两个只调用实际实现的方法,并在每个方法上放置不同的 [Queue] 属性。

通常,如果我需要在开发/生产之间切换队列,我只想用 isTestOrder=boolean 调用 RunOrder(...) 之类的东西,而不用担心那个级别的队列。

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'
}

请注意 _ 的用法以表明这些并不意味着直接调用。我不记得 hangfire 方法是否需要 public,但如果确实需要,那么 _ 更重要。

如果你想改变队列动态你可以按照这种方式。

此实现适用于所有 EnqueueScheduleContinueJobWith

技巧发生在 [Queue("{0}")]。 Hangfire 将使用 String.Format("{0}", job.Args) 将作业参数传递给给定模式 ("{0}"),以便在 每次状态更改 时获取实际队列,因此将应用目标队列 即使重试.

突出显示的代码语法:

// 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
}

完全实现:

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
    }
}