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'.
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).
IJobListener
has a JobToBeExecuted
and a JobWasExecuted
method. The latter provides a JobExecutionException
so that you know when something went wrong. However, there is no way to correlate JobToBeExecuted
and JobWasExecuted
. Suppose my job runs for ten minutes. I start it at t0
and t0+2
(so they overlap). I get two calls to JobToBeExecuted
and insert two start times into my history table. When both jobs finish at t1
and t1+2
I get two calls to JobWasExecuted
. How do I know what database record to update in each call开发者_StackOverflow社区 (to store an end time with its corresponding start time)?
ITriggerListener
has another problem. There is no way to get any errors inside the TriggerComplete
method when a job failed.
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
.
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.
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). 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
:
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);
}
精彩评论