Lines
100.00%
21 / 21
Functions and Methods
100.00%
7 / 7
Classes and Traits
100.00%
1 / 1
| Name | Lines | Functions and Methods | CRAP | Classes and Traits | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| RegistryEntityUpdateRequestHandler | 100.00% | 21 / 21 | 100.00% | 7 / 7 | 11 | 100.00% | 1 / 1 | |||
| __construct | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| handledMessageClass | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| handle | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| updateOnHomeAssistant | 100.00% | 4 / 4 | 100.00% | 1 / 1 | 3 | |||||
| warnIfExposed | 100.00% | 8 / 8 | 100.00% | 1 / 1 | 2 | |||||
| sendUpdate | 100.00% | 4 / 4 | 100.00% | 1 / 1 | 2 | |||||
| previewUpdate | 100.00% | 2 / 2 | 100.00% | 1 / 1 | 1 | |||||
| 1 | <?php | |
| 2 | ||
| 3 | declare(strict_types=1); | |
| 4 | ||
| 5 | namespace Stewart\Runtime\Broker\Message; | |
| 6 | ||
| 7 | use Psr\Log\LoggerInterface; | |
| 8 | use Stewart\Client\HaClient; | |
| 9 | use Stewart\Contracts\Exception\RegistryEditException; | |
| 10 | use Stewart\Contracts\Registry\RegisteredEntity; | |
| 11 | use Stewart\Runtime\Broker\Exposure\ExposureLink; | |
| 12 | use Stewart\Runtime\Broker\HaCallSlots; | |
| 13 | use Stewart\Runtime\Broker\HaSession; | |
| 14 | use Stewart\Runtime\Broker\WorkerHandle; | |
| 15 | use Stewart\Runtime\Config\ServiceCallPolicy; | |
| 16 | use Stewart\Runtime\Ipc\Message\RegistryEntityUpdateRequest; | |
| 17 | use Stewart\Runtime\Ipc\Message\RegistryEntityUpdateResult; | |
| 18 | use Stewart\Runtime\Ipc\Message\WorkerMessage; | |
| 19 | ||
| 20 | /** @implements WorkerMessageHandler<RegistryEntityUpdateRequest> */ | |
| 21 | final readonly class RegistryEntityUpdateRequestHandler implements WorkerMessageHandler | |
| 22 | { | |
| 23 | public function __construct( | |
| 24 | private HaSession $session, | |
| 25 | private HaClient $client, | |
| 26 | private ExposureLink $exposures, | |
| 27 | private HaCallSlots $slots, | |
| 28 | private ServiceCallPolicy $policy, | |
| 29 | private LoggerInterface $logger, | |
| 30 | ) {} | |
| 31 | ||
| 32 | public function handledMessageClass(): string | |
| 33 | { | |
| 34 | return RegistryEntityUpdateRequest::class; | |
| 35 | } | |
| 36 | ||
| 37 | /** @param RegistryEntityUpdateRequest $message */ | |
| 38 | public function handle(WorkerHandle $handle, WorkerMessage $message): void | |
| 39 | { | |
| 40 | $this->slots->runBounded($handle, $message, fn(): RegistryEntityUpdateResult => $this->updateOnHomeAssistant($message)); | |
| 41 | } | |
| 42 | ||
| 43 | /** @throws RegistryEditException */ | |
| 44 | private function updateOnHomeAssistant(RegistryEntityUpdateRequest $request): RegistryEntityUpdateResult | |
| 45 | { | |
| 46 | if (!$this->session->isConnected()) { | |
| 47 | throw $request->createUnreachableFailure('Home Assistant is disconnected'); | |
| 48 | } | |
| 49 | ||
| 50 | $this->warnIfExposed($request); | |
| 51 | ||
| 52 | return new RegistryEntityUpdateResult($request->correlationId, $this->policy->dryRun ? $this->previewUpdate($request) : $this->sendUpdate($request)); | |
| 53 | } | |
| 54 | ||
| 55 | private function warnIfExposed(RegistryEntityUpdateRequest $request): void | |
| 56 | { | |
| 57 | $exposure = $this->exposures->findAddressByEntityId($request->entityId); | |
| 58 | ||
| 59 | if ($exposure === null) { | |
| 60 | return; | |
| 61 | } | |
| 62 | ||
| 63 | $this->logger->warning('Editing the registry entry of an entity a Stewart app exposes; its handle owns the name and icon', [ | |
| 64 | 'entity' => $request->entityId->value, | |
| 65 | 'app' => $exposure->appId->value, | |
| 66 | 'key' => $exposure->key->value, | |
| 67 | ]); | |
| 68 | } | |
| 69 | ||
| 70 | /** @throws RegistryEditException */ | |
| 71 | private function sendUpdate(RegistryEntityUpdateRequest $request): RegisteredEntity | |
| 72 | { | |
| 73 | $update = $request->update->needsCurrentEntry() | |
| 74 | ? $request->update->resolveAgainst($this->client->getEntityRegistryEntry($request->entityId)->toRegisteredEntity()) | |
| 75 | : $request->update; | |
| 76 | ||
| 77 | return $this->client->updateEntityRegistryEntry($request->entityId, $update)->toRegisteredEntity(); | |
| 78 | } | |
| 79 | ||
| 80 | /** @throws RegistryEditException */ | |
| 81 | private function previewUpdate(RegistryEntityUpdateRequest $request): RegisteredEntity | |
| 82 | { | |
| 83 | $this->logger->info('Registry entry not updated: service_calls.dry_run is on', ['entity' => $request->entityId->value]); | |
| 84 | ||
| 85 | return $request->update->applyTo($this->client->getEntityRegistryEntry($request->entityId)->toRegisteredEntity()); | |
| 86 | } | |
| 87 | } |