在Quartz.net中,如何在一定时间内延迟所有预定作业?

时间:2017-08-17 15:54:36

标签: c# quartz.net quartz.net-2.0

我正在使用Quartz.net来安排各种API调用。 我使用的API限制了每个时间段可以发出的请求数量,如果超过了,那么我的帐户将在下一分钟受到处罚(无需提出请求)。

如果我收到通知,说我提出了太多请求,并且我的帐户将在下一分钟受到限制,我将需要确保在此期间没有预定的工作。我怎样才能最好地将所有预定作业的解雇时间推迟一两分钟?

我原本打算调用Scheduler.GetTriggerKeys()并循环并更新每个现有的触发器,如下所示:

foreach(var triggerKey in SchedInstance.GetTriggerKeys(GroupMatcher<TriggerKey>.AnyGroup()))
{
    var oldTrigger = SchedInstance.GetTrigger(triggerKey);
    TriggerBuilder tb = oldTrigger.GetTriggerBuilder();
    // Update the schedule associated with the builder and build the new trigger
    tb.StartAt(oldTrigger.StartTimeUtc.AddSeconds(63));
    var newTrigger = tb.Build();
    SchedInstance.RescheduleJob(oldTrigger.Key, newTrigger);
}

这是正确的方法还是最好只是在相同的时间段内停止调度程序然后重新启动它?

1 个答案:

答案 0 :(得分:1)

您有几种可能性来实现这一目标。 如您所述,您可以停止调度程序或循环触发器。但这听起来对我来说不是最好的选择。

<强> TriggerListener

您可以实现ITriggerListener界面并使用VetoJobExecution()方法。实现可能如下所示:

public class SystemThrottledTriggerListener : ITriggerListener
{
    public string Name => "System Throttled Trigger Listener";

    public void TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode)
    {
        // no need for implementation
    }

    public void TriggerFired(ITrigger trigger, IJobExecutionContext context)
    {
        // no need for implementation
    }

    public void TriggerMisfired(ITrigger trigger)
    {
        // no need for implementation
    }

    public bool VetoJobExecution(ITrigger trigger, IJobExecutionContext context)
    {
        // If you return true, then the Trigger is vetoed and the job is not executed.
        // The Job will automatically scheduled for his next execution
        return IsSystemThrottled();
    }
}

然后只需将监听器添加到您的调度程序中,如果您的系统受到限制,所有触发器都会被否决:

Scheduler.ListenerManager.AddTriggerListener(new SystemThrottledTriggerListener());

<强> JobExecutionException

您可以抛出JobExecutionException来停止执行您的工作。为此,您需要在执行开始时检查系统是否受到限制,然后抛出异常。这是Quartz的唯一例外,您可以告诉Quartz它应该立即重新启动作业。将吞下所有其他异常并停止执行作业。 实现可能如下所示:

public class MyJob : IJob
{
    public void Execute(IJobExecutionContext context)
    {
        if(IsSystemThrottled())
            throw new JobExecutionException(true);

        // your other stuff
    }
}

如果使用参数true创建例外,则作业将立即生效。并且会一次又一次地重新启动,直到您的系统不再被限制为止。

如果你有很多工作,我建议你使用一个可以抛出JobExecutionException的工作基类,你只能从这个类派生你的工作。