Lines
90.00%
18 / 20
Methods
75.00%
3 / 4
Classes
0.00%
0 / 1
| Name | Lines | Methods | CRAP | ||||
|---|---|---|---|---|---|---|---|
| __construct | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| scheduleRefreshFor | 100.00% | 4 / 4 | 100.00% | 1 / 1 | 2 | ||
| startRefresh | 84.61% | 11 / 13 | 0.00% | 0 / 1 | 3.03 | ||
| refreshAndBroadcast | 100.00% | 2 / 2 | 100.00% | 1 / 1 | 2 | ||
| 16 | final class RegistryRefresher | |
| 17 | { | |
| 18 | private const array REFRESHING_EVENT_TYPES = [ | |
| 19 | 'area_registry_updated', | |
| 20 | 'floor_registry_updated', | |
| 21 | 'label_registry_updated', | |
| 22 | 'device_registry_updated', | |
| 23 | 'entity_registry_updated', | |
| 24 | ]; | |
| 25 | ||
| 26 | private const int QUIET_PERIOD_MILLISECONDS = 1000; | |
| 27 | ||
| 28 | private ?TimerHandle $pendingRefresh = null; | |
| 29 | ||
| 30 | private bool $refreshing = false; | |
| 31 | ||
| 32 | private bool $refreshRequestedWhileRefreshing = false; | |
| 33 | ||
| 34 | public function __construct( | |
| 35 | private readonly HaSession $session, | |
| 36 | private readonly WorkerSlotRegistry $slots, | |
| 37 | private readonly Timers $timers, | |
| 38 | private readonly LoggerInterface $logger, | |
| 39 | ) {} | |
| 40 | ||
| 41 | public function scheduleRefreshFor(HaEvent $event): void | |
| 42 | { | |
| 43 | if (!\in_array($event->type, self::REFRESHING_EVENT_TYPES, true)) { | |
| 44 | return; | |
| 45 | } | |
| 46 | ||
| 47 | $this->pendingRefresh?->cancel(); | |
| 48 | $this->pendingRefresh = $this->timers->startTimer(Duration::milliseconds(self::QUIET_PERIOD_MILLISECONDS), $this->startRefresh(...)); | |
| 49 | } | |
| 50 | ||
| 51 | private function startRefresh(): void | |
| 52 | { | |
| 53 | $this->pendingRefresh = null; | |
| 54 | ||
| 55 | if ($this->refreshing) { | |
| 56 | $this->refreshRequestedWhileRefreshing = true; | |
| 57 | ||
| 58 | return; | |
| 59 | } | |
| 60 | ||
| 61 | $this->refreshing = true; | |
| 62 | ||
| 63 | async(function (): void { | |
| 64 | try { | |
| 65 | do { | |
| 66 | $this->refreshRequestedWhileRefreshing = false; | |
| 67 | $this->refreshAndBroadcast(); | |
| 68 | } while ($this->refreshRequestedWhileRefreshing); | |
| 69 | } catch (Throwable $e) { | |
| 70 | $this->logger->error('Failed refreshing the Home Assistant registry', ['exception' => $e]); | |
| 71 | } finally { | |
| 72 | $this->refreshing = false; | |
| 73 | } | |
| 74 | })->ignore(); | |
| 75 | } | |
| 76 | ||
| 77 | private function refreshAndBroadcast(): void | |
| 78 | { | |
| 79 | if ($this->session->refreshRegistry()) { | |
| 80 | $this->slots->broadcast($this->session->snapshotRegistry()->toRegistrySnapshot()); | |
| 81 | } | |
| 82 | } | |
| 83 | } |