简体   繁体   English

如何使用Quartz调度程序维护作业历史记录

[英]How to maintain a job history using Quartz scheduler

I'd like to maintain a history of jobs that were scheduled by a Quartz scheduler containing the following properties: 'start time', 'end time', 'success', 'error'. 我想保留由Quartz调度程序安排的作业历史,其中包含以下属性:“开始时间”,“结束时间”,“成功”,“错误”。

There are two interfaces available for this: ITriggerListener and IJobListener (I'm using the C# naming convention for interfaces because I'm using Quartz.NET but the same question could be asked for the Java version). 有两个可用的接口: ITriggerListenerIJobListener (我正在使用接口的C#命名约定,因为我使用的是Quartz.NET,但可能会要求Java版本提出相同的问题)。

IJobListener has a JobToBeExecuted and a JobWasExecuted method. IJobListener有一个JobToBeExecuted和一个JobWasExecuted方法。 The latter provides a JobExecutionException so that you know when something went wrong. 后者提供了一个JobExecutionException以便您知道什么时候出错了。 However, there is no way to correlate JobToBeExecuted and JobWasExecuted . 但是,无法关联JobToBeExecutedJobWasExecuted Suppose my job runs for ten minutes. 假设我的工作运行了十分钟。 I start it at t0 and t0+2 (so they overlap). 我在t0t0+2开始它(所以它们重叠)。 I get two calls to JobToBeExecuted and insert two start times into my history table. 我得到两次对JobToBeExecuted调用,并在我的历史表中插入两个开始时间。 When both jobs finish at t1 and t1+2 I get two calls to JobWasExecuted . 当两个作业都在t1t1+2结束时,我得到两次对JobWasExecuted调用。 How do I know what database record to update in each call (to store an end time with its corresponding start time)? 我如何知道每次调用中要更新的数据库记录(存储结束时间及其相应的开始时间)?

ITriggerListener has another problem. ITriggerListener还有另一个问题。 There is no way to get any errors inside the TriggerComplete method when a job failed. 作业失败时,无法在TriggerComplete方法中获取任何错误。

How do I get the desired behavior? 我如何获得所需的行为?

The way to do this is to generate an identifier in JobToBeExecuted , store it in the JobExecutionContext and retrieve it again from the JobExecutionContext in JobWasExecuted . 要做到这一点的方法是产生一个标识符JobToBeExecuted ,其存储在JobExecutionContext从再次检索它JobExecutionContextJobWasExecuted

public void JobToBeExecuted(JobExecutionContext context)
{
    // Insert history record and retrieve primary key of inserted record.
    long historyId = InsertHistoryRecord(...);
    context.Put("HistoryIdKey", historyId);
}

public void JobWasExecuted(JobExecutionContext context,
                           JobExecutionException jobException)
{
    // Retrieve history id from context and update history record.
    long historyId = (long) context.Get("HistoryIdKey");
    UpdateHistoryRecord(historyId, ...);
}

The scheduler has to maintain a key that lets it correlate each history entry. 调度程序必须维护一个密钥,使其关联每个历史记录条目。 There must be a unique job ID of some kind that's created when a job kicks off to be able to accomplish this. 必须有一个独特的工作ID,当工作开始时能够实现这一点。

You don't mention such a thing, so I thought it was worth a suggestion. 你没有提到这样的事情,所以我认为值得一个建议。

UPDATE: I'd INSERT a record into the database when a job is created and get back the primary key (maybe a GUID). 更新:我在创建作业时将记录插入数据库并返回主键(可能是GUID)。 I'd use that as the key. 我会用它作为关键。

If you're happy to just update the database at the end, you can get the job name and run time from the IJobExecutionContext : 如果您很乐意在最后更新数据库,则可以从IJobExecutionContext获取作业名称和运行时间:

public void JobWasExecuted(JobExecutionContext context,
                       JobExecutionException jobException)
{
    var sql = @"INSERT INTO MyJobAuditHistory 
                (JobKey, RunTime, Status, Exception) VALUES (?, ?, ?, ?)";

    // create command etc.
    command.Parameters.Add(context.JobDetail.Key.ToString());
    command.Parameters.Add(context.JobRunTime);
    command.Parameters.Add(jobException == null ? "Success" : "Fail");
    command.Parameters.Add(jobException == null ? null : jobException.Message);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM