在Job构造函数抛出异常后从触发器ERROR状态恢复?

时间:2015-08-28 14:35:46

标签: quartz.net quartz.net-2.0

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

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

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

我看过没有决议的其他参考文献:

6 个答案:

答案 0 :(得分:5)

当触发器实例化IJob类时发生异常,然后触发将其更改为TRIGGER_STATE为ERROR,然后在此状态下触发将不再触发。

要重新启用触发器,您需要更改它陈述等待,然后它可以再次开火。 这里举例说明你如何重新启用你的失误触发器。

var trigerKey = new TriggerKey("trigerKey", "trigerGroup");
if (scheduler.GetTriggerState(trigerKey) == TriggerState.Error)
{
    scheduler.ResumeTrigger(trigerKey);
}

答案 1 :(得分:3)

为了记录,我认为这是Quartz的设计缺陷。如果一项工作不能建造一次,那并不意味着它不能永远建造。这是一个瞬态错误,应该这样对待。停止所有未来的预定工作违反了最不惊讶的原则。

无论如何,我的黑客解决方案是捕获由于我的作业构造而导致的任何错误,而不是抛出错误或返回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);
    }
}

答案 2 :(得分:2)

  

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

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

  

此方法抛出异常应该极为罕见 -   基本上只有在没有办法实例化的情况下   并准备工作以执行。当抛出异常时,   调度程序会将与作业关联的所有触发器移动到需要人员的状态   干预(例如,在修复之后应用程序重启   配置问题导致实例化Job的问题。

答案 3 :(得分:1)

简单地说,你应该遵循良好的面向对象的实践:构造函数不应该抛出异常。尝试将配置数据拉到作业的执行阶段(Execute方法),以便正确处理重试。这可能意味着通过允许提取数据的构造函数提供service / func。

答案 4 :(得分: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

答案 5 :(得分:0)

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

<块引用>

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

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

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

this github discussion 中的更多信息。