Lines 100.00% 9 / 9
Methods 100.00% 7 / 7
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 isOpen 100.00% 1 / 1 100.00% 1 / 1 1
 holdEvent 100.00% 1 / 1 100.00% 1 / 1 1
 openWindow 100.00% 1 / 1 100.00% 1 / 1 1
 cancelWindowTimer 100.00% 1 / 1 100.00% 1 / 1 1
 settleWindow 100.00% 2 / 2 100.00% 1 / 1 2
 reopenAndForward 100.00% 2 / 2 100.00% 1 / 1 1
15final class ThrottleWindow
16{
17    /** @var PendingEmission<T> */
18    private readonly PendingEmission $pending;
19
20    /**
21     * @param Closure(T): void $downstream
22     * @param Closure(): void $onClosed
23     */
24    public function __construct(
25        Timers $timers,
26        Duration $windowLength,
27        SubscriptionScope $scope,
28        int $stage,
29        private readonly Closure $downstream,
30        private readonly Closure $onClosed,
31    ) {
32        $this->pending = new PendingEmission($timers, $windowLength, $scope, $stage);
33    }
34
35    public function isOpen(): bool
36    {
37        return $this->pending->isArmed();
38    }
39
40    /** @param T $event */
41    public function holdEvent(mixed $event): void
42    {
43        $this->pending->hold($event);
44    }
45
46    public function openWindow(): void
47    {
48        $this->pending->arm($this->settleWindow(...));
49    }
50
51    public function cancelWindowTimer(): void
52    {
53        $this->pending->disarm();
54    }
55
56    private function settleWindow(): void
57    {
58        if (!$this->pending->flushInto($this->reopenAndForward(...))) {
59            ($this->onClosed)();
60        }
61    }
62
63    /** @param T $held */
64    private function reopenAndForward(mixed $held): void
65    {
66        $this->openWindow();
67
68        ($this->downstream)($held);
69    }
70}