只有累積,沒有奇蹟

2023年1月15日 星期日

[.NET] Quartz.NET 排程執行異常 - All triggers of Job class set to ERROR state.

問題 
最近因為新專案需求是定期到資料庫檢查會員的資料,因此使用 ASP.NET Core Hosting 服務 +  Quartz.NET 作為工作排程器使用,在開發完畢要啟動 Job 驗證正確性時意外跳出異常訊息,錯誤訊息為  Quartz.Simpl.RAMJobStore | All triggers of Job GroupName.ClassName set to ERROR state. ,這篇就針對此案例作簡單紀錄與分享若是有不清楚或是錯誤的地方歡迎討論予糾正

解決方法 
首先先看一下案發現場的錯誤 log 如下
上面可以看到當程式啟動時所紀錄的 Log 資訊,像是有紀錄目前所使用的版本為 3.0.7 版,預設 ThreadPool 為 10 條,但一到 QuartzScheduler 啟動之後下一個 Log 就直接紀錄執行異常 ( ERROR STATE ),搜尋相關異常訊息發現以下資訊
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).
可能問題為 Quartz.NET 啟動此 Trigger 當下發生錯誤,有可能是因為沒有辦法實例化或是準備執行 Job 發生異常,當執行拋出異常時會將有關聯的作業關閉,會自動更新異常 TRIGGER_STATE 狀態為 ERROR state,需要人工進行修復,修復完畢後再重新啟用應用程式。因此下一步是了解啟動時發生的錯誤資訊,為了得到相關錯誤訊息,調整既有的代碼將  JobExecutionException  資訊紀錄在 log.Error 中,
class SomeJob : IJob
{
    private readonly ILogger _logger;
    private readonly IMemberService _service;

    public SomeJob(IMemberService service, ILogger logger)
    {
        this._service = service;
        this._logger = logger;
    }
    
    public Task Execute(IJobExecutionContext context)
    {
        try
        {
            // todo something
        }
        catch (Exception e)
        {
            JobExecutionException je = new JobExecutionException(e);
            je.RefireImmediately = true;  //do something with the exception

            _logger.Error(je);
            
            return Task.FromResult(0);
        }

        return Task.FromResult(0);
    }
}
接著重新執行應用程式,並觀察 Log 資訊
果不其然,透過 Log 可以發現是在 Service 的建構子 ctor 注入時發生錯誤,所以才會在排程要啟動時異常
停止此 Job 的執行動作,在往下追發現是其 interface 存取修飾子設定異常 ( 應該要是 public 實際卻是 internal ),修正後在重新執行可以看到下列 Log,
Quartz.Core.QuartzSchedulerThread|Batch acquisition of 1 triggers |url: |action: 
執行正常,宣告結案 !

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

0 意見:

張貼留言

Copyright © m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com