I'm currently developing job manager based on Quartz.net
. I want to be able to display job execution status in real time so when job interruption request is made I could save context.JobDetail.JobDataMap.Put("status", "interrupting");
in job data map and read this status by fetching all currently executing jobs in scheduler. But, the problem, is I do not have access to IJobExecutionContext
context object directly in Interrupt()
method, so I cannot set interrupting status immediately at the moment interruption was requested. This is the functionality I basically want to achieve:
class InterruptedException : Exception { }
[PersistJobDataAfterExecution, DisallowConcurrentExecution]
class MyJob : IInterruptableJob
{
private bool _interrupted;
private void AssertContinue()
{
if (_interrupted) throw new InterruptedException();
}
public void Execute(IJobExecutionContext context)
{
try
{
context.JobDetail.JobDataMap.Put("status", "started");
AssertContinue();
// Do the work
AssertContinue();
context.JobDetail.JobDataMap.Put("status", "completed");
}
catch (InterruptedException)
{
// Set interrupted status when job is actually interrupted
context.JobDetail.JobDataMap.Put("status", "interrupted");
}
catch
{
// log any othe errors but set interrupted status only on InterruptedException
}
}
public void Interrupt()
{
_interrupted = true;
// I want to set interrupting statues here!!!
context.JobDetail.JobDataMap.Put("status", "interrupting");
}
}
The basic idea of IInterruptableJob
interface implementation, as I understand, is to set some _interrupted
flag value to true
inside void Interrupt()
method, then check this flag value on each execution step in Execute()
method. So, basically, we cannot interrupt the job immediately, we can make interruption request, and only when interruption status check is executed we can interrupt the job by throwing an exception, for example. But I want to set interrupting status for my job during this short period of time. How can I do that? Is it even possible to get IJobExecutionContext context
object in Interrupt()
method?
Well, the solution turns out to be pretty obvious and easy. I just have to create private
IJobExecutionContext _context = null;
field of my job class and set it's value to context
in Execute()
method.
public void Execute(IJobExecutionContext context)
{
_context = context;
...
}
Basically we can interrupt only the executing job so if Interrupt()
is called than Execute()
was called at least once so this approach, basically, suits my needs and updates job's DataMap
immediately after Interrupt
was called.