Time as the ports see it: an instant in milliseconds and a UTC day. A port never reads a clock itself (there is none to read in a Worker's pure code); it is handed the moment.
An instant, in milliseconds since the Unix epoch.
One UTC day, counted from the epoch. The natural voice's daily allowance is spent against one of these, so two backends in different time zones still agree on when "today" ends.
The moment the following day begins: when a spent daily allowance frees up.
What time it is now. Sync because every backend can answer from memory (Date.now(), the system
clock) and a port that had to await the time would make every decision a suspension point.
A clock that only moves when told to, for the in-memory adapter and for tests.
60impl ManualClock { 61 pub fn at(ms: u64) -> Self { 62 Self(std::sync::atomic::AtomicU64::new(ms)) 63 } 64 65 pub fn set(&self, at: Millis) { 66 trace!("manual clock set to {} ms", at.get()); 67 self.0.store(at.get(), std::sync::atomic::Ordering::SeqCst); 68 } 69 70 pub fn advance(&self, ms: u64) { 71 trace!("manual clock advances {ms} ms"); 72 self.0.fetch_add(ms, std::sync::atomic::Ordering::SeqCst); 73 } 74} 75 76impl Clock for ManualClock { 77 fn now(&self) -> Millis { 78 Millis::new(self.0.load(std::sync::atomic::Ordering::SeqCst)) 79 } 80} 81 82#[cfg(test)] 83mod tests { 84 use super::*; 85 86 #[test] 87 fn a_day_ends_when_the_next_one_begins() { 88 let d = Day::containing(Millis::new(DAY_MS * 5 + 17)); 89 assert_eq!(d.number(), 5); 90 assert_eq!(d.ends_at(), Millis::new(DAY_MS * 6)); 91 assert_eq!(Day::containing(d.ends_at()).number(), 6, "the next day starts exactly there"); 92 assert_eq!(Day::containing(Millis::new(d.ends_at().get() - 1)), d); 93 } 94 95 #[test] 96 fn the_manual_clock_moves_only_when_told() { 97 let c = ManualClock::at(10); 98 assert_eq!(c.now(), Millis::new(10)); 99 c.advance(5); 100 assert_eq!(c.now().get(), 15); 101 c.set(Millis::new(3)); 102 assert_eq!(c.now().get(), 3); 103 } 104}