1

I am using Quartz.net to schedule various API calls. The API I am using restricts the number of requests that can be made per time period and if that is exceeded, then my account is penalized for the next minute (no requests can be made).

If I ever receive a notification that I have made too many requests and my account will be throttled for the next minute, I will need to ensure that no scheduled jobs fire during that period. How can I best delay firing of all scheduled jobs by a minute or two?

I was originally intending to call Scheduler.GetTriggerKeys() and loop over and update every existing trigger like so:

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

Is this the right approach or would it be better to simply stop the scheduler for the same time period and then restart it?

4

1 回答 1

1

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

触发器监听器

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

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

        // your other stuff
    }
}

如果使用参数创建异常true,作业将立即重新启动。并且会一次又一次地重新启动,直到您的系统不再受到限制。

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

于 2017-08-22T09:21:35.050 回答