Lines 100.00% 17 / 17
Methods 100.00% 9 / 9
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 occursAtAll 100.00% 1 / 1 100.00% 1 / 1 1
 start 100.00% 3 / 3 100.00% 1 / 1 1
 dueAt 100.00% 4 / 4 100.00% 1 / 1 2
 isDue 100.00% 1 / 1 100.00% 1 / 1 2
 delayUntilDue 100.00% 1 / 1 100.00% 1 / 1 1
 advance 100.00% 4 / 4 100.00% 1 / 1 1
 isRecurring 100.00% 1 / 1 100.00% 1 / 1 1
 describe 100.00% 1 / 1 100.00% 1 / 1 1
13final class ElapsedTrigger implements Trigger
14{
15    private MonotonicTime $anchor;
16
17    private ?MonotonicTime $due = null;
18
19    public function __construct(
20        private readonly ElapsedSchedule $schedule,
21        private readonly Clock $clock,
22    ) {
23        $this->anchor = $clock->getMonotonicTime();
24    }
25
26    public function occursAtAll(): bool
27    {
28        return $this->schedule->findNextDueAfter($this->anchor, $this->anchor) !== null;
29    }
30
31    public function start(): bool
32    {
33        // Intervals count from going live, not from being armed.
34        $this->anchor = $this->clock->getMonotonicTime();
35        $this->due = $this->schedule->findNextDueAfter($this->anchor, $this->anchor);
36
37        return $this->due !== null;
38    }
39
40    public function dueAt(): ?Instant
41    {
42        if ($this->due === null) {
43            return null;
44        }
45
46        $offset = $this->due->toMicroseconds() - $this->clock->getMonotonicTime()->toMicroseconds();
47
48        return Instant::fromEpochMicroseconds($this->clock->getNow()->toEpochMicroseconds() + $offset);
49    }
50
51    public function isDue(): bool
52    {
53        return $this->due !== null && !$this->clock->getMonotonicTime()->isBefore($this->due);
54    }
55
56    public function delayUntilDue(): ?Duration
57    {
58        return $this->due?->elapsedSince($this->clock->getMonotonicTime());
59    }
60
61    public function advance(): int
62    {
63        $now = $this->clock->getMonotonicTime();
64        $due = $this->due ?? $now;
65        $this->due = $this->schedule->findNextDueAfter($this->anchor, $now);
66
67        return $this->schedule->countMissedBetween($due, $now);
68    }
69
70    public function isRecurring(): bool
71    {
72        return $this->schedule->isRecurring();
73    }
74
75    public function describe(): string
76    {
77        return $this->schedule->describe();
78    }
79}