Lines
88.88%
24 / 27
Methods
75.00%
6 / 8
Classes
0.00%
0 / 1
| Name | Lines | Methods | CRAP | ||||
|---|---|---|---|---|---|---|---|
| __construct | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| openCommand | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| settleThroughHandler | 100.00% | 8 / 8 | 100.00% | 1 / 1 | 3 | ||
| acceptCommand | 85.71% | 6 / 7 | 0.00% | 0 / 1 | 3.03 | ||
| rejectCommand | 100.00% | 3 / 3 | 100.00% | 1 / 1 | 2 | ||
| refuseUnknownCommand | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | ||
| takeOpenCommand | 100.00% | 3 / 3 | 100.00% | 1 / 1 | 1 | ||
| sendAnswer | 33.33% | 1 / 3 | 0.00% | 0 / 1 | 3.19 | ||
| 18 | final class ExposedCommandSettlements | |
| 19 | { | |
| 20 | /** @var WeakMap<ExposedCommand, OpenExposedCommand> */ | |
| 21 | private WeakMap $openCommands; | |
| 22 | ||
| 23 | public function __construct( | |
| 24 | private readonly Transport $transport, | |
| 25 | private readonly LoggerInterface $logger, | |
| 26 | ) { | |
| 27 | $this->openCommands = new WeakMap(); | |
| 28 | } | |
| 29 | ||
| 30 | public function openCommand(string $commandId, ExposedCommand $command, ExposedHandle $handle): void | |
| 31 | { | |
| 32 | $this->openCommands[$command] = new OpenExposedCommand($commandId, $handle); | |
| 33 | } | |
| 34 | ||
| 35 | /** | |
| 36 | * @template T of ExposedCommand | |
| 37 | * | |
| 38 | * @param T $command | |
| 39 | * @param Closure(T): mixed $handler | |
| 40 | * @throws Throwable | |
| 41 | */ | |
| 42 | public function settleThroughHandler(ExposedCommand $command, Closure $handler): void | |
| 43 | { | |
| 44 | try { | |
| 45 | $handler($command); | |
| 46 | } catch (CommandException $e) { | |
| 47 | $this->rejectCommand($command, $e->getMessage()); | |
| 48 | ||
| 49 | return; | |
| 50 | } catch (Throwable $e) { | |
| 51 | $this->rejectCommand($command, 'The app failed to handle the command.'); | |
| 52 | ||
| 53 | throw $e; | |
| 54 | } | |
| 55 | ||
| 56 | $this->acceptCommand($command); | |
| 57 | } | |
| 58 | ||
| 59 | public function acceptCommand(ExposedCommand $command): void | |
| 60 | { | |
| 61 | $open = $this->takeOpenCommand($command); | |
| 62 | ||
| 63 | if ($open === null) { | |
| 64 | return; | |
| 65 | } | |
| 66 | ||
| 67 | $requestedState = $command->getRequestedState(); | |
| 68 | ||
| 69 | if ($requestedState !== null) { | |
| 70 | $open->handle->recordCommandedState($requestedState); | |
| 71 | } | |
| 72 | ||
| 73 | $this->sendAnswer(new ExposedCommandAnswered($open->commandId, true)); | |
| 74 | } | |
| 75 | ||
| 76 | public function rejectCommand(ExposedCommand $command, string $reason): void | |
| 77 | { | |
| 78 | $open = $this->takeOpenCommand($command); | |
| 79 | ||
| 80 | if ($open !== null) { | |
| 81 | $this->sendAnswer(new ExposedCommandAnswered($open->commandId, false, $reason)); | |
| 82 | } | |
| 83 | } | |
| 84 | ||
| 85 | public function refuseUnknownCommand(string $commandId, string $reason): void | |
| 86 | { | |
| 87 | $this->sendAnswer(new ExposedCommandAnswered($commandId, false, $reason)); | |
| 88 | } | |
| 89 | ||
| 90 | private function takeOpenCommand(ExposedCommand $command): ?OpenExposedCommand | |
| 91 | { | |
| 92 | $open = $this->openCommands[$command] ?? null; | |
| 93 | unset($this->openCommands[$command]); | |
| 94 | ||
| 95 | return $open; | |
| 96 | } | |
| 97 | ||
| 98 | private function sendAnswer(ExposedCommandAnswered $answer): void | |
| 99 | { | |
| 100 | try { | |
| 101 | $this->transport->send($answer); | |
| 102 | } catch (TransportException $e) { | |
| 103 | $this->logger->debug('Could not answer an exposed entity command; the broker channel is closed', ['exception' => $e, 'command' => $answer->commandId]); | |
| 104 | } | |
| 105 | } | |
| 106 | } |