Search code examples
spring-bootjobrunr

JobRunr Spring Boot: how to get notified if a recurring job - including retries - has failed


I'm using jobrunr 5.1.4 in my spring boot application. I have a simple service declaring a recurring job which allows for some retries. A single failing job run is not that relevant for me. Instead, I'm interested in getting notified after all jobs, i.e. the initial job including all the retries, have failed.

I thought JobRunr's JobServerFilter would be a good idea. But the onProcessed() method never gets triggered in case of an exception only in case of a successful job run. And the ApplyStateFilter gets triggered on every state change. Far too often for my requirement. Leaving me clueless, if a change to a FAILED state was the last in a series of jobs belonging together (initial job + allowed retried jobs).

A simple example would look like this:

@Service
public class JobScheduler {

  @Job(name = "My Recurring Job", retries = 2, jobFilters = ExceptionFilter.class)
  @Recurring(id = "my-recurring-job", cron = "*/10 * * * *")
  public void recurringJob() {
    throw new RuntimeException("foo");
  }
}

A basic implementation of my JobFilter looks like this:

@Component
public class ExceptionFilter implements JobServerFilter, ApplyStateFilter {

  @Override
  public void onProcessing(Job job) {
    log.info("onProcessing: {}", job.getJobName());
    log.info(job.getJobState().getName().name());
  }

  @Override
  public void onProcessed(Job job) {
    log.info("onProcessed: {}", job.getJobName());
    log.info(job.getJobState().getName().name());
  }

  @Override
  public void onStateApplied(Job job, JobState jobState1, JobState jobState2) {
    log.info("onStateApplied: {}", job.getJobName());
    log.info("jobState1: {}", jobState1.getName().name());
    log.info("jobState2: {}", jobState2.getName().name());
  }
}

Is this use case even possible with JobRunr? Or does anyone have an idea how to solve this issue in a different way?

Thank you very much in advance for you support.


Solution

  • I think you're on the right track with onStateApplied from ApplyStateFilter.

    You can use the following approach:

      @Override
      public void onStateApplied(Job job, JobState oldState, JobState newState) {
        if (isFailed(newState) && maxAmountOfRetriesReached(job)) {
          // your logic here
        }
      }
    

    OnProcessed is not triggered as your job was not processed (due to the failure).