View Javadoc

1   package com.atlassian.scheduler.quartz1;
2   
3   import org.quartz.JobDetail;
4   import org.quartz.JobPersistenceException;
5   import org.quartz.Trigger;
6   import org.quartz.core.SchedulingContext;
7   import org.quartz.impl.jdbcjobstore.JobStoreTX;
8   import org.slf4j.Logger;
9   import org.slf4j.LoggerFactory;
10  
11  import javax.annotation.Nullable;
12  import java.sql.Connection;
13  import java.util.concurrent.locks.ReentrantLock;
14  
15  import static com.atlassian.scheduler.core.util.LogWarn.logWarn;
16  
17  /**
18   * Quartz breaks if a bad job class is seen during scheduler recovery (at startup),
19   * leading to the scheduler failing to start.  This patches the normal {@code JobStoreTX}
20   * to avoid the problem by logging a warning instead of failing to start the scheduler.
21   */
22  public class Quartz1HardenedJobStore extends JobStoreTX {
23      private static final Logger LOG = LoggerFactory.getLogger(Quartz1HardenedJobStore.class);
24  
25      private final ReentrantLock recoverJobsLock = new ReentrantLock();
26  
27      @Override
28      protected void recoverJobs() throws JobPersistenceException {
29          recoverJobsLock.lock();
30          try {
31              super.recoverJobs();
32          } finally {
33              recoverJobsLock.unlock();
34          }
35      }
36  
37      @Override
38      protected void storeTrigger(Connection conn, SchedulingContext ctxt, Trigger newTrigger, @Nullable JobDetail job,
39                                  boolean replaceExisting, String state, boolean forceState, boolean recovering)
40              throws JobPersistenceException {
41          try {
42              super.storeTrigger(conn, ctxt, newTrigger, job, replaceExisting, state, forceState, recovering);
43          } catch (JobPersistenceException jpe) {
44              // We don't actually expect this lock to ever be contended.  We just need to know if this thread
45              // has traversed "recoverJobs" on the way here, and lock ownership is a convenient way to find out.
46              if (!recoverJobsLock.isHeldByCurrentThread()) {
47                  throw jpe;
48              }
49              logWarn(LOG, "Caught an exception storing trigger during scheduler recovery", jpe);
50          }
51      }
52  }