Lines 100.00% 18 / 18
Methods 100.00% 6 / 6
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 recordCommand 100.00% 4 / 4 100.00% 1 / 1 1
 takeCommandAnsweredBy 100.00% 5 / 5 100.00% 1 / 1 2
 takeCommandsOf 100.00% 4 / 4 100.00% 1 / 1 2
 forgetExpiredCommands 100.00% 3 / 3 100.00% 1 / 1 3
 forgetCommand 100.00% 1 / 1 100.00% 1 / 1 1
13final class PendingExposureCommands
14{
15    /** @var array<string, ExposedEntityCommand> */
16    private array $commandsById = [];
17
18    /** @var array<string, MonotonicTime> */
19    private array $expiriesById = [];
20
21    public function __construct(
22        private readonly Clock $clock,
23        private readonly ExposeConfig $expose,
24    ) {}
25
26    public function recordCommand(ExposedEntityCommand $command): void
27    {
28        $now = $this->clock->getMonotonicTime();
29        $this->forgetExpiredCommands($now);
30        $this->commandsById[$command->commandId] = $command;
31        $this->expiriesById[$command->commandId] = $now->plus($this->expose->commandTimeout);
32    }
33
34    public function takeCommandAnsweredBy(string $commandId, WorkerId $workerId): ?ExposedEntityCommand
35    {
36        $command = $this->commandsById[$commandId] ?? null;
37
38        if ($command?->owner?->equals($workerId) !== true) {
39            return null;
40        }
41
42        $this->forgetCommand($commandId);
43
44        return $command;
45    }
46
47    /** @return list<ExposedEntityCommand> */
48    public function takeCommandsOf(WorkerId $workerId): array
49    {
50        $taken = array_values(array_filter($this->commandsById, static fn(ExposedEntityCommand $command): bool => $command->owner?->equals($workerId) === true));
51
52        foreach ($taken as $command) {
53            $this->forgetCommand($command->commandId);
54        }
55
56        return $taken;
57    }
58
59    private function forgetExpiredCommands(MonotonicTime $now): void
60    {
61        foreach ($this->expiriesById as $commandId => $expiry) {
62            if ($now->isAfter($expiry)) {
63                $this->forgetCommand($commandId);
64            }
65        }
66    }
67
68    private function forgetCommand(string $commandId): void
69    {
70        unset($this->commandsById[$commandId], $this->expiriesById[$commandId]);
71    }
72}