Lines 100.00% 14 / 14
Functions and Methods 100.00% 5 / 5
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
RestartBudget 100.00% 14 / 14 100.00% 5 / 5 6 100.00% 1 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 countUsedAttempts 100.00% 1 / 1 100.00% 1 / 1 1
 claimAttempt 100.00% 7 / 7 100.00% 1 / 1 2
 forgetAttempts 100.00% 1 / 1 100.00% 1 / 1 1
 listAttemptsWithinWindow 100.00% 4 / 4 100.00% 1 / 1 1
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Runtime\Broker;
6
7use Stewart\Contracts\Time\MonotonicTime;
8use Stewart\Runtime\Config\SupervisionConfig;
9use Stewart\Runtime\Model\WorkerId;
10
11final class RestartBudget
12{
13    /** @var array<int, list<MonotonicTime>> */
14    private array $restarts = [];
15
16    public function __construct(
17        private readonly SupervisionConfig $supervision,
18    ) {}
19
20    public function countUsedAttempts(WorkerId $workerId, MonotonicTime $now): int
21    {
22        return \count($this->listAttemptsWithinWindow($workerId, $now));
23    }
24
25    public function claimAttempt(WorkerId $workerId, MonotonicTime $now): ?int
26    {
27        $spent = $this->listAttemptsWithinWindow($workerId, $now);
28
29        if (\count($spent) >= $this->supervision->restartAttempts) {
30            $this->restarts[$workerId->value] = $spent;
31
32            return null;
33        }
34
35        $spent[] = $now;
36        $this->restarts[$workerId->value] = $spent;
37
38        return \count($spent);
39    }
40
41    public function forgetAttempts(WorkerId $workerId): void
42    {
43        unset($this->restarts[$workerId->value]);
44    }
45
46    /** @return list<MonotonicTime> */
47    private function listAttemptsWithinWindow(WorkerId $workerId, MonotonicTime $now): array
48    {
49        return array_values(array_filter(
50            $this->restarts[$workerId->value] ?? [],
51            fn(MonotonicTime $at): bool => $this->supervision->restartWindow->isLongerThan($now->elapsedSince($at)),
52        ));
53    }
54}