1 /**
2  * Defines the interface which all schedules implement, and some utilities that
3  * go along with the schedule concept.
4  */
5 module scheduled.schedule;
6 
7 import std.datetime;
8 import std.typecons;
9 
10 /** 
11  * A schedule that governs when a job should be executed.
12  */
13 public interface JobSchedule {
14     /**
15      * Gets the timestamp at which the scheduler should plan to execute a job
16      * with this schedule next.
17      */
18     Nullable!SysTime getNextExecutionTime(SysTime currentTime) const;
19 
20     /**
21      * Marks the schedule as having been executed at the given time.
22      */
23     void markExecuted(SysTime executionTime);
24 
25     /**
26      * Tells whether the schedule is repeating; that jobs with this schedule
27      * should be re-queued after being executed.
28      * Returns: True if this schedule is repeating, or false otherwise.
29      */
30     bool isRepeating() const;
31 }
32 
33 /**
34  * Simple wrapper interface for obtaining the current system time.
35  */
36 public interface CurrentTimeProvider {
37     /** 
38      * Gets the current system time.
39      * Returns: The current system time.
40      */
41     SysTime now() const;
42 }
43 
44 /** 
45  * Standard implementation of the current time provider, which simply returns
46  * the current system time.
47  */
48 public class SysTimeProvider : CurrentTimeProvider {
49     SysTime now() const {
50         return Clock.currTime;
51     }
52 }
53 
54 /**
55  * Tests the functionality of the system time provider.
56  */
57 unittest {
58     import core.thread;
59     auto provider = new SysTimeProvider;
60     for (int i = 0; i < 10; i++) {
61         auto duration = provider.now - Clock.currTime;
62         assert(duration < msecs(100), "System time provider's time does not match expected.");
63         Thread.sleep(msecs(10));
64     }
65 }
66 
67 /** 
68  * Implementation of the current time provider which always returns a fixed
69  * value, useful for testing.
70  */
71 public class FixedTimeProvider : CurrentTimeProvider {
72     private SysTime currentTime;
73 
74     this(SysTime currentTime) {
75         this.currentTime = currentTime;
76     }
77 
78     SysTime now() const {
79         return this.currentTime;
80     }
81 
82     public void incrementTime(Duration dur) {
83         this.currentTime += dur;
84     }
85 
86     public void setTime(SysTime newTime) {
87         this.currentTime = newTime;
88     }
89 }
90 
91 /**
92  * Tests the functionality of the fixed time provider.
93  */
94 unittest {
95     import core.thread;
96     SysTime time = SysTime(DateTime(2021, 9, 22, 22, 34, 57));
97     auto provider = new FixedTimeProvider(time);
98     assert(provider.now == time, "Fixed time provider's time does not match expected.");
99     Thread.sleep(seconds(1));
100     assert(provider.now == time, "Fixed time provider's time does not match expected.");
101 }