5

在使用 Quartz.net 调度作业时,我偶尔会在实例化作业时收到异常。这反过来会导致 Quartz 将作业的触发器设置为错误状态。发生这种情况时,触发器将停止触发,直到发生一些手动干预(重新启动服务,因为我正在使用内存中的作业调度)。

如何防止设置错误状态,或者至少告诉 Quartz 重试处于错误状态的触发器?

异常的原因是由于获取传递给作业构造函数的配置数据所需的不稳定的网络调用。我正在使用自定义 IJobFactory 来执行此操作。

我已经看到其他没有解决方案的参考:

4

6 回答 6

12

作为记录,我认为这是 Quartz 的设计缺陷。如果一个工作不能被构建一次,那并不意味着它不能总是被构建。这是一个暂时性错误,应该这样对待。停止所有未来的计划作业违反了最小惊讶原则。

无论如何,我的 hack 解决方案是捕获由于我的作业构造而导致的任何错误,而不是抛出错误或返回 null 以返回自定义 IJob,而不是简单地记录错误。这并不完美,但至少它不会阻止将来触发该工作。

public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
    try
    {
        var job = this.container.Resolve(bundle.JobDetail.JobType) as IJob;
        return job;
    }
    catch (Exception ex)
    {
        this.logger.Error(ex, "Exception creating job. Giving up and returning a do-nothing logging job.");
        return new LoggingJob(this.logger);
    }
}
于 2015-08-31T16:14:12.330 回答
6

当触发器初始化类发生异常时IJob,触发器将其TRIGGER_STATE更改为ERROR,然后该状态的触发器将不再触发。

要重新启用触发器,您需要将其状态更改为 WAITING,然后它可以再次触发。这里是您如何重新启用您的失火触发器的示例。

var trigerKey = new TriggerKey("trigerKey", "trigerGroup");
if (scheduler.GetTriggerState(trigerKey) == TriggerState.Error)
{
    scheduler.ResumeTrigger(trigerKey);
}
于 2016-11-11T17:33:42.777 回答
2

如何防止设置错误状态,或者至少告诉 Quartz 重试处于错误状态的触发器?

不幸的是,在当前版本中,您无法重试这些触发器。根据 Quartz 的文档,

这种方法抛出异常应该是非常罕见的——基本上只有在根本没有办法实例化和准备 Job 以执行的情况下。当抛出异常时,调度程序会将与作业关联的所有触发器移入状态,这将需要人工干预(例如,在修复导致实例化作业问题的任何配置问题后重新启动应用程序)。

于 2015-08-28T16:30:55.840 回答
2

简而言之,您应该遵循良好的面向对象实践:构造函数不应该抛出异常。尝试将配置数据的拉取移动到作业的执行阶段(执行方法),在该阶段将正确处理重试。这可能意味着通过允许提取数据的构造函数提供服务/函数。

于 2015-08-31T08:53:44.620 回答
1

实际上,从 ERROR 状态重置 Trigger 的最佳方法是:

private final SchedulerFactoryBean schedulerFactoryBean;
Scheduler scheduler = schedulerFactoryBean.getScheduler();

TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);
if (scheduler.getTriggerState(triggerKey).equals(Trigger.TriggerState.ERROR)) {
    scheduler.resetTriggerFromErrorState(triggerKey);
}

笔记:

您不应该手动修改来自第三方库或软件的表中的记录。如果有任何功能,则应通过 API 对该库进行所有更改。

JobStoreSupport.resetTriggerFromErrorState

于 2021-01-21T11:13:32.637 回答
0

将触发器状态更改WAITING为作者还建议一种方法可以是手动更新数据库。

[...]您可能需要手动更新数据库,但是是的 - 如果无法实例化作业,这被认为是非常糟糕的事情,Quartz 会将它们标记为已损坏。

我创建了另一个在应用程序启动时安排的作业,更新处于错误状态的触发器以恢复它们。

UPDATE QRTZ_TRIGGERS SET [TRIGGER_STATE] = 'WAITING' WHERE [TRIGGER_STATE] = 'ERROR'

此 github 讨论中的更多信息。

于 2021-01-18T15:25:47.270 回答