在 Quartz.net 中,如何将所有计划的作业延迟一定的时间跨度?

In Quartz.net, how can I delay all scheduled jobs by a certain time span?

我正在使用 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);
}

这是正确的方法还是在同一时间段内简单地停止调度程序然后重新启动它会更好?

您有两种可能性来实现这一点。 正如您所说,您可以停止调度程序或遍历触发器。但这对我来说听起来不是最好的选择。

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 的工作库 class,你只能从这个 class.

中派生你的工作。