Recover from trigger ERROR state after Job constructor threw an exception?

烈酒焚心 提交于 2019-12-04 10:21:11

For the record, I consider this a design flaw of Quartz. If a job can't be constructed once, that doesn't mean it can't always be constructed. This is a transient error and should be treated as such. Stopping all future scheduled jobs violates the principle of least astonishment.

Anyway, my hack solution is to catch any errors that are the result of my job construction and instead of throwing an error or returning null to return a custom IJob instead that simply logs an error. This isn't perfect, but at least it doesn't prevent future triggering of the job.

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

When exception occurs on trigger instatiating IJob class, then trigger change it TRIGGER_STATE to ERROR, and then trigger in this state will no longer fire.

To reenable trigger your need to change it state to WAITING, and then it could to fire again. Here the example how your can reenable yours misfired trigger.

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

How can I prevent the error state from being set, or at the very least, tell Quartz to retry triggers that are in the error state?

Unfortunately, in current version, you cannot retry those triggers. As per the documentation of Quartz,

It should be extremely rare for this method to throw an exception - basically only the case where there is no way at all to instantiate and prepare the Job for execution. When the exception is thrown, the Scheduler will move all triggers associated with the Job into the state, which will require human intervention (e.g. an application restart after fixing whatever configuration problem led to the issue with instantiating the Job).

Simply put, you should follow good object oriented practices: constructors should not throw exceptions. Try to move pulling of configuration data to job's execution phase (Execute method) where retries will be handled correctly. This might mean providing a service/func via constructor that allows pulling the data.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!