Deleting jobs

Cancel any job, whether it is scheduled, enqueued or already processing

Sometimes you may want to delete a job that is scheduled, enqueued or already processing. This can be done easily via the Dashboard or even programmatically.

JobId jobId = BackgroundJob.enqueue(() -> myService.doWork());

BackgroundJob.delete(jobId);
Thanks to the BackgroundJob.delete method, the job that was enqueued earlier on can be deleted.

When the job is still enqueued or scheduled, things are easy - JobRunr changes the state of your Job to Deleted and all is well.

However, if the job is already processing, JobRunr will try to interrupt the thread that is currently processing the job. Most of the JDK and third party libraries that do I/O will be able to listen for the thread interrupt signal and throw an InterruptedException. As a primer on how Thread interruption works, I advise to read the Baeldung article on how to Handle InterruptedException in Java.

The purpose of the interrupt system is to provide a well-defined framework for allowing threads to interrupt tasks (potentially time-consuming ones) in other threads.

If you have code that can throw an InterruptedException, things are easy - let JobRunr handle it:

public void doWorkThatTakesLong(int seconds) throws InterruptedException {
    TimeUnit.SECONDS.sleep(seconds);
    System.out.println("WORK IS DONE!!!!!!!!");
}
The sleep method throws the checked InterruptedException. JobRunr supports this and will handle it gracefully.

If you decide to catch the InterruptedException for some reason, it is important to either rethrow that same exception or interrupt the current thread itself.

public void doWorkThatTakesLong(int seconds) throws InterruptedException {
    try {
        TimeUnit.SECONDS.sleep(seconds);
        System.out.println("WORK IS DONE!!!!!!!!");
    } catch (InterruptedException e) {
        System.out.println("Thread has been interrupted");
        throw e; // it is important to rethrow / propagate the InterruptedException
    }
}
In this example, the InterruptedException is caught but re-thrown so that JobRunr can handle it gracefully.
public void doWorkThatTakesLongInterruptThread(int seconds) {
    try {
        TimeUnit.SECONDS.sleep(seconds);
        System.out.println("WORK IS DONE!!!!!!!!");
    } catch (InterruptedException e) {
        System.out.println("Thread has been interrupted");
        Thread.currentThread().interrupt();
    }
}
If you cannot rethrow the InterruptedException, it is important to interrupt the current thread.

If you don’t have any code that does I/O or it does not adhere to the standard interrupt framework, this means your code is basically uninterruptible and the job will keep running until it finishes (either succeeds or fails).

To solve this, you check in certain places of your own job method whether the thread is interrupted (as JobRunr will signal the thread that is running the job to interrupt when it is deleted).

while (true) {
    if (Thread.currentThread().isInterrupted()) throw new InterruptedException();
    // do some work
}
By manually checking if the current thread is interrupted, you can throw an InterrupedException that will be handled by JobRunr.

More examples can be found in the JobRunr end-to-end tests.