Lines 100.00% 18 / 18
Functions and Methods 100.00% 2 / 2
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
Reconnector 100.00% 18 / 18 100.00% 2 / 2 8 100.00% 1 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 retryUntilConnected 100.00% 17 / 17 100.00% 1 / 1 7
1<?php
2
3declare(strict_types=1);
4
5namespace Stewart\Runtime\Broker;
6
7use Amp\Cancellation;
8use Amp\CancelledException;
9use Closure;
10use Psr\Log\LoggerInterface;
11use Psr\Log\LogLevel;
12use Stewart\Client\Exception\HaClientException;
13use Stewart\Runtime\Config\StewartConfig;
14use Stewart\Support\Time\Deadlines;
15use Throwable;
16
17final readonly class Reconnector
18{
19    public function __construct(
20        private StewartConfig $config,
21        private LoggerInterface $logger,
22        private Deadlines $deadlines,
23    ) {}
24
25    /** @param Closure(): void $attempt */
26    public function retryUntilConnected(Closure $attempt, Cancellation $stop): void
27    {
28        for ($failures = 0; !$stop->isRequested(); ++$failures) {
29            try {
30                $attempt();
31
32                return;
33            } catch (Throwable $e) {
34                if ($e instanceof HaClientException && $e->reason->isFatal()) {
35                    throw $e;
36                }
37
38                $this->logger->log(
39                    $failures === 0 ? LogLevel::ERROR : LogLevel::WARNING,
40                    'Could not reach Home Assistant',
41                    ['exception' => $e, 'attempt' => $failures + 1],
42                );
43            }
44
45            try {
46                $stop->throwIfRequested();
47
48                $delay = $this->config->reconnectBackoff->delayFor($failures + 1);
49
50                $this->logger->info('Retrying Home Assistant', ['in' => (string) $delay, 'attempt' => $failures + 2]);
51                $this->deadlines->delay($delay, $stop);
52            } catch (CancelledException) {
53                return;
54            }
55        }
56    }
57}