From d1105a1e89d3e9a240444174ab582352fb2860e1 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Tue, 17 Sep 2024 11:28:02 +0200 Subject: [PATCH] refs #659. Trace API. New endpoint execute in command --- config/api_platform/Command.yaml | 7 ++++ config/api_platform/Trace.yaml | 20 +++++++++ config/services.yaml | 5 +++ migrations/Version20240917091950.php | 35 ++++++++++++++++ migrations/Version20240917092207.php | 31 ++++++++++++++ src/Controller/CommandExecuteAction.php | 44 +++++++++++++++++++ src/Dto/Input/CommandExecuteInput.php | 17 ++++++++ src/Dto/Output/ClientOutput.php | 8 ++-- src/Dto/Output/CommandOutput.php | 4 +- src/Dto/Output/TraceOutput.php | 50 ++++++++++++++++++++++ src/Entity/Trace.php | 14 +++---- src/Model/TraceStatus.php | 33 +++++++++++++++ src/State/Provider/TraceProvider.php | 56 +++++++++++++++++++++++++ 13 files changed, 311 insertions(+), 13 deletions(-) create mode 100644 config/api_platform/Trace.yaml create mode 100644 migrations/Version20240917091950.php create mode 100644 migrations/Version20240917092207.php create mode 100644 src/Controller/CommandExecuteAction.php create mode 100644 src/Dto/Input/CommandExecuteInput.php create mode 100644 src/Dto/Output/TraceOutput.php create mode 100644 src/Model/TraceStatus.php create mode 100644 src/State/Provider/TraceProvider.php diff --git a/config/api_platform/Command.yaml b/config/api_platform/Command.yaml index f8480ce..fa14e2b 100644 --- a/config/api_platform/Command.yaml +++ b/config/api_platform/Command.yaml @@ -24,6 +24,13 @@ resources: ApiPlatform\Metadata\Post: ~ ApiPlatform\Metadata\Delete: ~ + execute: + class: ApiPlatform\Metadata\Post + method: POST + input: App\Dto\Input\CommandExecuteInput + uriTemplate: /commands/{uuid}/execute + controller: App\Controller\CommandExecuteAction + properties: App\Entity\Command: id: diff --git a/config/api_platform/Trace.yaml b/config/api_platform/Trace.yaml new file mode 100644 index 0000000..c7e74db --- /dev/null +++ b/config/api_platform/Trace.yaml @@ -0,0 +1,20 @@ +resources: + App\Entity\Trace: + output: App\Dto\Output\TraceOutput + normalizationContext: + groups: ['default', 'trace:read'] + operations: + ApiPlatform\Metadata\GetCollection: + provider: App\State\Provider\TraceProvider + filters: + - 'api_platform.filter.trace.order' + - 'api_platform.filter.trace.search' + ApiPlatform\Metadata\Get: + provider: App\State\Provider\TraceProvider + +properties: + App\Entity\Trace: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/services.yaml b/config/services.yaml index 4c0ac26..c9d2a91 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -113,6 +113,11 @@ services: $itemProvider: '@api_platform.doctrine.orm.state.item_provider' App\State\Provider\CommandTaskProvider: + bind: + $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' + $itemProvider: '@api_platform.doctrine.orm.state.item_provider' + + App\State\Provider\TraceProvider: bind: $collectionProvider: '@api_platform.doctrine.orm.state.collection_provider' $itemProvider: '@api_platform.doctrine.orm.state.item_provider' \ No newline at end of file diff --git a/migrations/Version20240917091950.php b/migrations/Version20240917091950.php new file mode 100644 index 0000000..7645fa2 --- /dev/null +++ b/migrations/Version20240917091950.php @@ -0,0 +1,35 @@ +addSql('CREATE TABLE trace (id INT AUTO_INCREMENT NOT NULL, client_id INT NOT NULL, command_id INT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, status VARCHAR(255) NOT NULL, output VARCHAR(255) DEFAULT NULL, executed_at DATETIME NOT NULL, finished_at DATETIME NOT NULL, UNIQUE INDEX UNIQ_315BD5A1D17F50A6 (uuid), INDEX IDX_315BD5A119EB6921 (client_id), INDEX IDX_315BD5A133E1689A (command_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE trace ADD CONSTRAINT FK_315BD5A119EB6921 FOREIGN KEY (client_id) REFERENCES client (id)'); + $this->addSql('ALTER TABLE trace ADD CONSTRAINT FK_315BD5A133E1689A FOREIGN KEY (command_id) REFERENCES command (id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE trace DROP FOREIGN KEY FK_315BD5A119EB6921'); + $this->addSql('ALTER TABLE trace DROP FOREIGN KEY FK_315BD5A133E1689A'); + $this->addSql('DROP TABLE trace'); + } +} diff --git a/migrations/Version20240917092207.php b/migrations/Version20240917092207.php new file mode 100644 index 0000000..f291bd8 --- /dev/null +++ b/migrations/Version20240917092207.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE trace CHANGE finished_at finished_at DATETIME DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE trace CHANGE finished_at finished_at DATETIME NOT NULL'); + } +} diff --git a/src/Controller/CommandExecuteAction.php b/src/Controller/CommandExecuteAction.php new file mode 100644 index 0000000..fbdfda9 --- /dev/null +++ b/src/Controller/CommandExecuteAction.php @@ -0,0 +1,44 @@ +clients; + + /** @var Client $client */ + foreach ($clients as $client) { + $trace = new Trace(); + $trace->setClient($client->getEntity()); + $trace->setCommand($command); + $trace->setStatus(TraceStatus::IN_PROGRESS); + $trace->setExecutedAt(new \DateTimeImmutable()); + + $this->entityManager->persist($trace); + } + + $this->entityManager->flush(); + + return new JsonResponse(data: 'Command executed successfully', status: Response::HTTP_OK); + } +} \ No newline at end of file diff --git a/src/Dto/Input/CommandExecuteInput.php b/src/Dto/Input/CommandExecuteInput.php new file mode 100644 index 0000000..4630a47 --- /dev/null +++ b/src/Dto/Input/CommandExecuteInput.php @@ -0,0 +1,17 @@ +command = new CommandOutput($trace->getCommand()); + $this->client = new ClientOutput($trace->getClient()); + $this->status = $trace->getStatus(); + $this->executedAt = $trace->getExecutedAt(); + $this->output = $trace->getOutput(); + $this->finishedAt = $trace->getFinishedAt(); + $this->createdAt = $trace->getCreatedAt(); + $this->createdBy = $trace->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Entity/Trace.php b/src/Entity/Trace.php index 2010979..1f2f318 100644 --- a/src/Entity/Trace.php +++ b/src/Entity/Trace.php @@ -24,10 +24,10 @@ class Trace extends AbstractEntity private ?string $output = null; #[ORM\Column(type: Types::DATETIME_MUTABLE)] - private ?\DateTimeImmutable $executedAt = null; + private ?\DateTimeInterface $executedAt = null; - #[ORM\Column(type: Types::DATETIME_MUTABLE)] - private ?\DateTimeImmutable $finishedAt = null; + #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + private ?\DateTimeInterface $finishedAt = null; public function getClient(): ?Client { @@ -77,24 +77,24 @@ class Trace extends AbstractEntity return $this; } - public function getExecutedAt(): ?\DateTimeImmutable + public function getExecutedAt(): ?\DateTimeInterface { return $this->executedAt; } - public function setExecutedAt(\DateTimeImmutable $executedAt): static + public function setExecutedAt(\DateTimeInterface $executedAt): static { $this->executedAt = $executedAt; return $this; } - public function getFinishedAt(): ?\DateTimeImmutable + public function getFinishedAt(): ?\DateTimeInterface { return $this->finishedAt; } - public function setFinishedAt(\DateTimeImmutable $finishedAt): static + public function setFinishedAt(\DateTimeInterface $finishedAt): static { $this->finishedAt = $finishedAt; diff --git a/src/Model/TraceStatus.php b/src/Model/TraceStatus.php new file mode 100644 index 0000000..fc790b2 --- /dev/null +++ b/src/Model/TraceStatus.php @@ -0,0 +1,33 @@ + 'Pendiente', + self::IN_PROGRESS => 'En progreso', + self::COMPLETED => 'Completado', + self::FAILED => 'Fallido', + ]; + + public static function getStatus(): array + { + return self::STATUS; + } + + public static function getTraceStatus(string $status): ?string + { + return self::STATUS[$status] ?? null; + } + + public static function getStatusKeys(): array + { + return array_keys(self::STATUS); + } +} \ No newline at end of file diff --git a/src/State/Provider/TraceProvider.php b/src/State/Provider/TraceProvider.php new file mode 100644 index 0000000..aeefd56 --- /dev/null +++ b/src/State/Provider/TraceProvider.php @@ -0,0 +1,56 @@ +provideCollection($operation, $uriVariables, $context); + case $operation instanceof Get: + return $this->provideItem($operation, $uriVariables, $context); + } + } + + private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object + { + $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context); + + $items = new \ArrayObject(); + foreach ($paginator->getIterator() as $item){ + $items[] = new TraceOutput($item); + } + + return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems()); + } + + public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null + { + $item = $this->itemProvider->provide($operation, $uriVariables, $context); + + if (!$item) { + throw new NotFoundHttpException('Trace not found'); + } + + return new TraceOutput($item); + } +}