1 /** 2 * Defines the job interface, and some simple utilities to go with it. 3 */ 4 module scheduled.job; 5 6 import std.datetime; 7 import scheduled.schedule; 8 9 /** 10 * A job is a task which is submitted to the scheduler, to be run one or more 11 * times, according to a given schedule. 12 */ 13 public interface Job { 14 /** 15 * The method which is called to execute this job. 16 */ 17 public void run(); 18 } 19 20 /** 21 * Simple job that executes a function. 22 */ 23 public class FunctionJob : Job { 24 /** 25 * The function to execute when this job is run. 26 */ 27 private void function() fn; 28 29 /** 30 * Constructs a job that will run the given function. 31 * Params: 32 * fn = The function to execute. 33 */ 34 this(void function() fn) { 35 this.fn = fn; 36 } 37 38 /** 39 * Runs the function. 40 */ 41 override public void run() { 42 this.fn(); 43 } 44 } 45 46 /** 47 * Represents a pairing of a Job with a schedule. This is a component that 48 * is utilized internally by Schedulers. 49 */ 50 package final class ScheduledJob { 51 /** 52 * The component which is used to obtain current timestamps. 53 */ 54 private const CurrentTimeProvider timeProvider; 55 56 /** 57 * The schedule which defines when the associated job will run. 58 */ 59 private JobSchedule schedule; 60 61 /** 62 * The job which will run according to the associated schedule. 63 */ 64 private Job job; 65 66 /** 67 * The unique id for this scheduled job, within the context of the 68 * scheduler that's responsible for it. This id should be unique among all 69 * jobs currently managed by the scheduler, but ids may be reused once old 70 * jobs are removed. 71 */ 72 private immutable long id; 73 74 /** 75 * Constructs a new pairing of a job and a schedule. 76 * Params: 77 * job = The job which is scheduled. 78 * schedule = The schedule that defines when the job will run. 79 * id = The unique id for this job. 80 * timeProvider = Provider of current timestamps. 81 */ 82 package this(Job job, JobSchedule schedule, long id, CurrentTimeProvider timeProvider) { 83 this.job = job; 84 this.schedule = schedule; 85 this.timeProvider = timeProvider; 86 this.id = id; 87 } 88 89 /** 90 * Constructs a new pairing of a job and a schedule, with the default 91 * system time provider. 92 * Params: 93 * job = The job which is scheduled. 94 * schedule = The schedule that defines when the job will run. 95 * id = The unique id for this job. 96 */ 97 package this(Job job, JobSchedule schedule, long id) { 98 this(job, schedule, id, new SysTimeProvider); 99 } 100 101 /** 102 * Gets the schedule from this pairing. 103 * Returns: The schedule. 104 */ 105 public JobSchedule getSchedule() { 106 return this.schedule; 107 } 108 109 /** 110 * Gets the job from this pairing. 111 * Returns: The job. 112 */ 113 public Job getJob() { 114 return this.job; 115 } 116 117 /** 118 * Gets the id for this scheduled job. 119 * Returns: The id. 120 */ 121 public long getId() { 122 return this.id; 123 } 124 125 /** 126 * Compares two scheduled jobs, such that jobs whose next execution time 127 * is earlier, are considered greater than others. 128 * Params: 129 * other = The object to compare to. 130 * Returns: 1 if this object is greater, -1 if this object is less, or 0 131 * otherwise. 132 */ 133 override int opCmp(Object other) { 134 if (auto otherJob = cast(ScheduledJob) other) { 135 if (this.getId() == otherJob.getId()) return 0; // Exit right away if we're comparing to the same scheduled job. 136 SysTime now = timeProvider.now; 137 auto t1 = this.getSchedule().getNextExecutionTime(now); 138 auto t2 = otherJob.getSchedule().getNextExecutionTime(now); 139 if (t1.isNull && t2.isNull) return 0; 140 if (!t1.isNull && t2.isNull) return 1; 141 if (t1.isNull) return -1; 142 return t2.get.opCmp(t1.get); 143 } else { 144 return 0; 145 } 146 } 147 } 148 149 /** 150 * Tests the functionality of comparing two scheduled jobs. 151 */ 152 unittest { 153 import std.experimental.logger; 154 import scheduled.schedules.one_time; 155 156 JobSchedule s1 = new OneTimeSchedule(msecs(50)); 157 JobSchedule s2 = new OneTimeSchedule(msecs(500)); 158 JobSchedule s3 = new OneTimeSchedule(msecs(2500)); 159 160 class IncrementJob : Job { 161 public uint x = 0; 162 public void run() { 163 x++; 164 logf(LogLevel.info, "Incrementing counter to %d.", x); 165 } 166 } 167 auto j = new IncrementJob; 168 169 ScheduledJob jobA = new ScheduledJob(j, s1, 1); 170 ScheduledJob jobA2 = new ScheduledJob(j, s1, 2); 171 ScheduledJob jobB = new ScheduledJob(j, s2, 3); 172 ScheduledJob jobC = new ScheduledJob(j, s3, 4); 173 assert(jobA > jobB); 174 assert(jobA >= jobA2 && jobA <= jobA2); 175 assert(jobB > jobC); 176 assert(jobA > jobC); 177 }