View Javadoc

1   package com.atlassian.scheduler.config;
2   
3   import com.atlassian.annotations.PublicApi;
4   import com.atlassian.scheduler.JobRunner;
5   import com.atlassian.scheduler.SchedulerService;
6   import com.atlassian.scheduler.status.JobDetails;
7   import com.google.common.collect.ImmutableMap;
8   
9   import javax.annotation.Nonnull;
10  import javax.annotation.Nullable;
11  import javax.annotation.concurrent.Immutable;
12  import java.io.Serializable;
13  import java.util.Date;
14  import java.util.Map;
15  
16  import static com.atlassian.scheduler.config.RunMode.RUN_ONCE_PER_CLUSTER;
17  import static com.atlassian.scheduler.util.Safe.copy;
18  import static com.atlassian.util.concurrent.Assertions.notNull;
19  
20  /**
21   * Configuration options available when scheduling a job to be run.  This is similar to
22   * {@link JobDetails}, but provides only the information that is relevant to configuring
23   * the job or for the job to reference when it is actually running.
24   *
25   * @see JobDetails
26   */
27  @Immutable
28  @PublicApi
29  public final class JobConfig {
30      static final Map<String, Serializable> NO_PARAMETERS = ImmutableMap.of();
31  
32      /**
33       * Creates a new job configuration for the specified job runner key.
34       * <p>
35       * By default, the job configuration will assume:
36       * </p>
37       * <ul>
38       * <li><code>{@link #withRunMode(RunMode) withRunMode}({@link RunMode#RUN_ONCE_PER_CLUSTER})</code></li>
39       * <li><code>{@link #withSchedule(Schedule) withSchedule}({@link Schedule#runOnce(Date) Schedule.runOnce}(new Date()))</code></li>
40       * <li><code>{@link #withParameters(Map) withParameters}(null)</code></li>
41       * </ul>
42       * <p>
43       * Any of which may be overridden by calling the appropriate method.  Note that chaining the
44       * methods is recommended, as these methods return an altered copy rather than modifiying the
45       * original {@code JobConfig} in place.  For example, use:
46       * </p>
47       * <pre><code>
48       *     JobConfig config = JobConfig.forJobRunnerKey("myJobToDoImportantThings")
49       *              .withSchedule(Schedule.forInterval(Date, long))
50       *              .withRunMode(RunMode.RUN_LOCALLY);
51       * </code></pre>
52       *
53       * @param jobRunnerKey the unique identifier used to
54       *                     {@link SchedulerService#registerJobRunner(JobRunnerKey, JobRunner) register}
55       *                     the {@link JobRunner}
56       * @return a job configuration for the specified job runner key that will use the default settings
57       */
58      public static JobConfig forJobRunnerKey(JobRunnerKey jobRunnerKey) {
59          notNull("jobRunnerKey", jobRunnerKey);
60          return new JobConfig(jobRunnerKey, RUN_ONCE_PER_CLUSTER, Schedule.runOnce(null), NO_PARAMETERS);
61      }
62  
63  
64      private final JobRunnerKey jobRunnerKey;
65      private final RunMode runMode;
66      private final Schedule schedule;
67      private final Map<String, Serializable> parameters;
68  
69      private JobConfig(JobRunnerKey jobRunnerKey, @Nullable RunMode runMode, @Nullable Schedule schedule,
70                        Map<String, Serializable> parameters) {
71          this.jobRunnerKey = jobRunnerKey;
72          this.runMode = (runMode != null) ? runMode : RUN_ONCE_PER_CLUSTER;
73          this.schedule = (schedule != null) ? schedule : Schedule.runOnce(null);
74  
75          // handled by withParameters and would be redundant elsewhere
76          //noinspection AssignmentToCollectionOrArrayFieldFromParameter
77          this.parameters = parameters;
78      }
79  
80  
81      @Nonnull
82      public JobRunnerKey getJobRunnerKey() {
83          return jobRunnerKey;
84      }
85  
86      @Nonnull
87      public RunMode getRunMode() {
88          return runMode;
89      }
90  
91      @Nonnull
92      public Schedule getSchedule() {
93          return schedule;
94      }
95  
96      @Nonnull
97      public Map<String, Serializable> getParameters() {
98          return parameters;
99      }
100 
101 
102     /**
103      * Returns a copy of this job config that will use the specified run mode
104      * instead of what it currently uses.
105      *
106      * @param runMode the new run mode; may be {@code null}, in which case the default
107      *                {@link RunMode#RUN_ONCE_PER_CLUSTER} is used
108      * @return the new job configuration; the original is left unchanged
109      */
110     public JobConfig withRunMode(RunMode runMode) {
111         return new JobConfig(jobRunnerKey, runMode, schedule, parameters);
112     }
113 
114     /**
115      * Returns a copy of this job config that will use the specified schedule
116      * instead of what it currently uses.
117      *
118      * @param schedule the new schedule; may be {@code null}, in which case the default
119      *                 {@link Schedule#runOnce(Date) runOnce(new Date())} is used
120      * @return the new job configuration; the original is left unchanged
121      */
122     public JobConfig withSchedule(Schedule schedule) {
123         return new JobConfig(jobRunnerKey, runMode, schedule, parameters);
124     }
125 
126     /**
127      * Returns a copy of this job config that will use the specified parameters
128      * instead of what it currently uses.
129      * <p>
130      * <strong>WARNING</strong>: The parameters map must be serializable, so all of its
131      * contents must be as well.  Using objects that are not serializable, even as data
132      * members of objects that are themselves serializable, will usually fail.  Developers
133      * are encouraged to limit the information stored here to a few simple keys for
134      * accessing the runtime data that is needed instead of storing large objects,
135      * injectable components, etc. in the {@code parameters} map.
136      * </p>
137      * <p>
138      * <strong>WARNING</strong>: The scheduler service assumes that the objects within the
139      * {@code parameters} map are immutable.  Modifying objects after they have been added
140      * to the parameters map may have unpredictable results.
141      * </p>
142      *
143      * @param parameters the new parameters; may be {@code null}, in which case the
144      *                   {@link JobRunner} is provided with an empty map at run time.  The map
145      *                   should contain only immutable, serializable data
146      * @return the new job configuration; the original is left unchanged
147      */
148     public JobConfig withParameters(@Nullable Map<String, Serializable> parameters) {
149         return new JobConfig(jobRunnerKey, runMode, schedule, copy(parameters));
150     }
151 
152 
153     @Override
154     public boolean equals(@Nullable final Object o) {
155         if (this == o) {
156             return true;
157         }
158         if (o == null || getClass() != o.getClass()) {
159             return false;
160         }
161 
162         final JobConfig other = (JobConfig) o;
163         return jobRunnerKey.equals(other.jobRunnerKey) &&
164                 runMode == other.runMode &&
165                 schedule.equals(other.schedule) &&
166                 parameters.equals(other.parameters);
167     }
168 
169     @Override
170     public int hashCode() {
171         int result = jobRunnerKey.hashCode();
172         result = 31 * result + runMode.hashCode();
173         result = 31 * result + schedule.hashCode();
174         result = 31 * result + parameters.hashCode();
175         return result;
176     }
177 
178     @Override
179     public String toString() {
180         return "JobConfig[jobRunnerKey=" + jobRunnerKey +
181                 ",runMode=" + runMode +
182                 ",schedule=" + schedule +
183                 ",parameters=" + parameters +
184                 ']';
185     }
186 }