Quartz 重新安排作业

针对需要重新安排作业的需求,有几种处理方法。

手动重试

当 Quartz 作业正在运行时,若未处理的异常逃离了 IJob 方法,Quartz 系统会将作业标记为错误状态。随后,你可以使用适合你系统中的任意方法重新安排该作业。

使用 JobExecutionException

一个简单的方法是利用 JobExecutionException 控制作业是否应立即重新触发。

public async Task Execute(IJobExecutionContext context)
{
    try
    {
        // 执行作业逻辑
    }
    catch (Exception ex)
    {
        throw new JobExecutionException(ex, refireImmediately: true)
        {
            UnscheduleFiringTrigger = true,
            UnscheduleAllTriggers = true
        };
    }
}

Polly 重试

如果作业仅仅需要重试其工作,你可以使用 Polly 策略将作业包裹起来,并利用策略定义来实现重试。请注意,使用 Polly 实现长时间重试会保持一个作业槽位,从而阻止作业引擎执行更多工作。

自我重新安排

如果你的作业需要更多时间,比如需要等待 5 分钟,IJobExecutionContext 可以访问调度器。你可以利用它来重新安排作业,并使其正常退出。

public async Task Execute(IJobExecutionContext context)
{
    // 某些情况发生,指示你需要延迟处理
    // 例如收到HTTP 429 - 请求过多的状态码
    var oldTrigger = context.Trigger;
    var newTrigger = TriggerBuilder.Create()
        .WithIdentity($"{oldTrigger.Key.Name}-retry", oldTrigger.Key.Group)
        .StartAt(DateTimeOffset.UtcNow.AddMinutes(5))
        .Build();
    await context.Scheduler.ScheduleJob(newTrigger);
}

自我取消安排

另一种方法是让作业每 5 分钟(或其他合适的时间间隔)运行一次,成功后自行取消。这种方法的优点是逻辑上更容易理解,但仍可能持续对下游服务进行调用。

public async Task Execute(IJobExecutionContext context)
{
    // 工作成功
    if(success)
    {
        await context.Scheduler.UnscheduleJob(context.Trigger.Key);
    }
}

GitHub 讨论

在本文档中