From 89f7f07514109746da32230aeaa03a2b51d8d5a8 Mon Sep 17 00:00:00 2001 From: Adrian Dumitrache Date: Tue, 23 Apr 2024 23:30:11 +0300 Subject: [PATCH] [CronJob/SonataIntegrationBundle] Add cron job execution state (#250) --- app/migrations/Version20240423100707.php | 33 ++++++++++++ packages/cron-job/CronJobProcessor.php | 14 +++++- packages/cron-job/Entity/CronJobExecution.php | 50 +++++++++++++++++++ .../ExecuteCronJobMessageHandler.php | 6 +-- packages/cron-job/README.md | 2 +- .../cron-job/Tests/CronJobProcessorTest.php | 33 +++++++++++- .../ExecuteCronJobMessageHandlerTest.php | 26 ++-------- .../CronJob/Admin/CronJobExecutionAdmin.php | 39 ++++++++++++++- .../CronJob/Controller/CronJobController.php | 9 ++-- .../Controller/CronJobExecutionController.php | 37 ++++++++++++++ .../DependencyInjection/Configuration.php | 2 + .../DrawSonataIntegrationExtension.php | 4 +- .../translations/DrawCronJobAdmin.en.yaml | 3 ++ .../translations/DrawCronJobSonata.en.yaml | 1 - .../list__action_acknowledge.html.twig | 8 +++ .../show__action_acknowledge.html.twig | 8 +++ .../DependencyInjection/ConfigurationTest.php | 3 +- ...IntegrationExtensionCronJobEnabledTest.php | 2 + 18 files changed, 237 insertions(+), 43 deletions(-) create mode 100644 app/migrations/Version20240423100707.php create mode 100644 packages/sonata-integration-bundle/CronJob/Controller/CronJobExecutionController.php create mode 100644 packages/sonata-integration-bundle/Resources/translations/DrawCronJobAdmin.en.yaml delete mode 100644 packages/sonata-integration-bundle/Resources/translations/DrawCronJobSonata.en.yaml create mode 100644 packages/sonata-integration-bundle/Resources/views/CronJob/CronJobExecution/list__action_acknowledge.html.twig create mode 100644 packages/sonata-integration-bundle/Resources/views/CronJob/CronJobExecution/show__action_acknowledge.html.twig diff --git a/app/migrations/Version20240423100707.php b/app/migrations/Version20240423100707.php new file mode 100644 index 00000000..ab841bed --- /dev/null +++ b/app/migrations/Version20240423100707.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE cron_job__cron_job_execution ADD state VARCHAR(20) DEFAULT \'requested\' NOT NULL'); + $this->addSql('CREATE INDEX state ON cron_job__cron_job_execution (state)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('DROP INDEX state ON cron_job__cron_job_execution'); + $this->addSql('ALTER TABLE cron_job__cron_job_execution DROP state'); + } +} diff --git a/packages/cron-job/CronJobProcessor.php b/packages/cron-job/CronJobProcessor.php index eb86fe43..9dbccfa3 100644 --- a/packages/cron-job/CronJobProcessor.php +++ b/packages/cron-job/CronJobProcessor.php @@ -38,14 +38,24 @@ public function queue(CronJob $cronJob, bool $force): void public function process(CronJobExecution $execution): void { + $manager = $this->managerRegistry->getManagerForClass(CronJobExecution::class); + + if (!$execution->isExecutable(new \DateTimeImmutable())) { + $execution->skip(); + $manager->flush(); + + return; + } + $event = $this->eventDispatcher->dispatch(new PreCronJobExecutionEvent($execution)); if ($event->isExecutionCancelled()) { + $execution->skip(); + $manager->flush(); + return; } - $manager = $this->managerRegistry->getManagerForClass(CronJobExecution::class); - $execution->start(); $manager->flush(); diff --git a/packages/cron-job/Entity/CronJobExecution.php b/packages/cron-job/Entity/CronJobExecution.php index f07c85a4..f179173e 100644 --- a/packages/cron-job/Entity/CronJobExecution.php +++ b/packages/cron-job/Entity/CronJobExecution.php @@ -9,9 +9,26 @@ #[ ORM\Entity, ORM\Table(name: 'cron_job__cron_job_execution'), + ORM\Index(fields: ['state'], name: 'state'), ] class CronJobExecution implements \Stringable { + public const STATE_REQUESTED = 'requested'; + public const STATE_RUNNING = 'running'; + public const STATE_TERMINATED = 'terminated'; + public const STATE_ERRORED = 'errored'; + public const STATE_SKIPPED = 'skipped'; + public const STATE_ACKNOWLEDGED = 'acknowledged'; + + public const STATES = [ + self::STATE_REQUESTED, + self::STATE_RUNNING, + self::STATE_TERMINATED, + self::STATE_ERRORED, + self::STATE_SKIPPED, + self::STATE_ACKNOWLEDGED, + ]; + #[ ORM\Id, ORM\GeneratedValue, @@ -22,6 +39,9 @@ class CronJobExecution implements \Stringable #[ORM\Column(name: 'requested_at', type: 'datetime_immutable', nullable: false)] private \DateTimeImmutable $requestedAt; + #[ORM\Column(name: 'state', type: 'string', length: 20, nullable: false, options: ['default' => self::STATE_REQUESTED])] + private string $state = self::STATE_REQUESTED; + #[ORM\Column(name: '`force`', type: 'boolean', nullable: false, options: ['default' => false])] private bool $force; @@ -74,6 +94,18 @@ public function getRequestedAt(): ?\DateTimeImmutable return $this->requestedAt; } + public function getState(): string + { + return $this->state; + } + + private function setState(string $state): self + { + $this->state = $state; + + return $this; + } + public function isForce(): bool { return $this->force; @@ -166,6 +198,7 @@ public function isExecutable(\DateTimeImmutable $dateTime): bool public function start(): void { $this + ->setState(self::STATE_RUNNING) ->setExecutionStartedAt(new \DateTimeImmutable()) ->setExecutionEndedAt(null); } @@ -173,6 +206,7 @@ public function start(): void public function end(): static { $this + ->setState(self::STATE_TERMINATED) ->setExitCode(0) ->setExecutionEndedAt($executionEndedAt = new \DateTimeImmutable()) ->setExecutionDelay( @@ -186,10 +220,26 @@ public function fail(?int $exitCode, ?array $error): void { $this ->end() + ->setState(self::STATE_ERRORED) ->setExitCode($exitCode) ->setError($error); } + public function acknowledge(): void + { + $this->setState(self::STATE_ACKNOWLEDGED); + } + + public function skip(): void + { + $this->setState(self::STATE_SKIPPED); + } + + public function canBeAcknowledged(): bool + { + return self::STATE_ERRORED === $this->getState(); + } + public function __toString(): string { return implode( diff --git a/packages/cron-job/MessageHandler/ExecuteCronJobMessageHandler.php b/packages/cron-job/MessageHandler/ExecuteCronJobMessageHandler.php index 2383036f..76a03aee 100644 --- a/packages/cron-job/MessageHandler/ExecuteCronJobMessageHandler.php +++ b/packages/cron-job/MessageHandler/ExecuteCronJobMessageHandler.php @@ -18,10 +18,6 @@ public function __construct( #[AsMessageHandler] public function handleExecuteCronJobMessage(ExecuteCronJobMessage $message): void { - if (!($execution = $message->getExecution())->isExecutable(new \DateTimeImmutable())) { - return; - } - - $this->cronJobProcessor->process($execution); + $this->cronJobProcessor->process($message->getExecution()); } } diff --git a/packages/cron-job/README.md b/packages/cron-job/README.md index 441c3533..8a9fb0d2 100644 --- a/packages/cron-job/README.md +++ b/packages/cron-job/README.md @@ -51,7 +51,7 @@ draw_sonata_integration: cron_job_execution: group: Cron Job entity_class: Draw\Component\CronJob\Entity\CronJobExecution - controller_class: sonata.admin.controller.crud + controller_class: Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobExecutionController icon: null label: Cron Job Execution pager_type: simple diff --git a/packages/cron-job/Tests/CronJobProcessorTest.php b/packages/cron-job/Tests/CronJobProcessorTest.php index 5bf6bcc4..fa0daa9f 100644 --- a/packages/cron-job/Tests/CronJobProcessorTest.php +++ b/packages/cron-job/Tests/CronJobProcessorTest.php @@ -148,6 +148,7 @@ public function testProcess( $this->cronJobProcessor->process($execution); + static::assertEquals(CronJobExecution::STATE_TERMINATED, $execution->getState()); static::assertNotNull($execution->getExecutionStartedAt()); static::assertNotNull($execution->getExecutionEndedAt()); static::assertEquals( @@ -225,6 +226,7 @@ public function testProcessWithError(): void $this->cronJobProcessor->process($execution); + static::assertEquals(CronJobExecution::STATE_ERRORED, $execution->getState()); static::assertNotNull($execution->getExecutionStartedAt()); static::assertNotNull($execution->getExecutionEndedAt()); static::assertNotNull($execution->getExecutionDelay()); @@ -232,6 +234,29 @@ public function testProcessWithError(): void static::assertNotNull($execution->getError()); } + public function testProcessWithInactiveCronJob(): void + { + $this->eventDispatcher + ->expects(static::never()) + ->method('dispatch'); + + $this->entityManager + ->expects(static::once()) + ->method('flush'); + + $this->processFactory + ->expects(static::never()) + ->method('createFromShellCommandLine'); + + $this->cronJobProcessor->process( + $execution = (new CronJob()) + ->setActive(false) + ->newExecution() + ); + + static::assertEquals(CronJobExecution::STATE_SKIPPED, $execution->getState()); + } + public function testProcessWithCancelledExecution(): void { $this->eventDispatcher @@ -245,7 +270,7 @@ public function testProcessWithCancelledExecution(): void ); $this->entityManager - ->expects(static::never()) + ->expects(static::once()) ->method('flush'); $this->processFactory @@ -253,12 +278,16 @@ public function testProcessWithCancelledExecution(): void ->method('createFromShellCommandLine'); $this->cronJobProcessor->process($execution); + + static::assertEquals(CronJobExecution::STATE_SKIPPED, $execution->getState()); } private function createCronJobExecution(string $command = 'bin/console draw:test:execute'): CronJobExecution { return new CronJobExecution( - (new CronJob())->setCommand($command), + (new CronJob()) + ->setActive(true) + ->setCommand($command), new \DateTimeImmutable(), false ); diff --git a/packages/cron-job/Tests/MessageHandler/ExecuteCronJobMessageHandlerTest.php b/packages/cron-job/Tests/MessageHandler/ExecuteCronJobMessageHandlerTest.php index 2790df7e..44b79db2 100644 --- a/packages/cron-job/Tests/MessageHandler/ExecuteCronJobMessageHandlerTest.php +++ b/packages/cron-job/Tests/MessageHandler/ExecuteCronJobMessageHandlerTest.php @@ -5,6 +5,7 @@ namespace Draw\Component\CronJob\Tests\MessageHandler; use Draw\Component\CronJob\CronJobProcessor; +use Draw\Component\CronJob\Entity\CronJob; use Draw\Component\CronJob\Entity\CronJobExecution; use Draw\Component\CronJob\Message\ExecuteCronJobMessage; use Draw\Component\CronJob\MessageHandler\ExecuteCronJobMessageHandler; @@ -33,32 +34,13 @@ public function testHandleExecuteCronJobMessage(): void $this->cronJobProcessor ->expects(static::once()) ->method('process') - ->with($execution = $this->createCronJobExecution()); + ->with($execution = (new CronJob())->newExecution()); $this->handler->handleExecuteCronJobMessage( new ExecuteCronJobMessage($execution) ); - } - - public function testHandleExecuteCronJobMessageWithNotExecutableExecution(): void - { - $this->cronJobProcessor - ->expects(static::never()) - ->method('process'); - - $this->handler->handleExecuteCronJobMessage( - new ExecuteCronJobMessage($this->createCronJobExecution(false)) - ); - } - - private function createCronJobExecution(bool $executable = true): CronJobExecution&MockObject - { - $execution = $this->createMock(CronJobExecution::class); - $execution - ->expects(static::any()) - ->method('isExecutable') - ->willReturn($executable); - return $execution; + static::assertEquals(CronJobExecution::STATE_REQUESTED, $execution->getState()); + static::assertNotNull($execution->getRequestedAt()); } } diff --git a/packages/sonata-integration-bundle/CronJob/Admin/CronJobExecutionAdmin.php b/packages/sonata-integration-bundle/CronJob/Admin/CronJobExecutionAdmin.php index c1c635b5..002d0c8e 100644 --- a/packages/sonata-integration-bundle/CronJob/Admin/CronJobExecutionAdmin.php +++ b/packages/sonata-integration-bundle/CronJob/Admin/CronJobExecutionAdmin.php @@ -4,13 +4,16 @@ namespace Draw\Bundle\SonataIntegrationBundle\CronJob\Admin; +use Draw\Component\CronJob\Entity\CronJobExecution; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Datagrid\DatagridMapper; use Sonata\AdminBundle\Datagrid\ListMapper; use Sonata\AdminBundle\Form\Type\ModelAutocompleteType; use Sonata\AdminBundle\Route\RouteCollectionInterface; use Sonata\AdminBundle\Show\ShowMapper; +use Sonata\DoctrineORMAdminBundle\Filter\ChoiceFilter; use Sonata\DoctrineORMAdminBundle\Filter\ModelFilter; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; class CronJobExecutionAdmin extends AbstractAdmin { @@ -29,6 +32,21 @@ protected function configureDatagridFilters(DatagridMapper $filter): void ] ) ->add('requestedAt') + ->add( + 'state', + ChoiceFilter::class, + [ + 'field_type' => ChoiceType::class, + 'field_options' => [ + 'multiple' => true, + 'choices' => array_combine( + CronJobExecution::STATES, + CronJobExecution::STATES + ), + ], + 'show_filter' => true, + ] + ) ->add('force') ->add('executionStartedAt') ->add('executionEndedAt') @@ -53,6 +71,7 @@ protected function configureListFields(ListMapper $list): void ] ) ->add('requestedAt') + ->add('state') ->add('force') ->add('executionStartedAt') ->add('executionEndedAt') @@ -64,6 +83,9 @@ protected function configureListFields(ListMapper $list): void [ 'actions' => [ 'show' => [], + 'acknowledge' => [ + 'template' => '@DrawSonataIntegration/CronJob/CronJobExecution/list__action_acknowledge.html.twig', + ], 'delete' => [], ], ] @@ -74,6 +96,7 @@ protected function configureShowFields(ShowMapper $show): void { $show ->add('requestedAt') + ->add('state') ->add('force') ->add('executionStartedAt') ->add('executionEndedAt') @@ -84,7 +107,20 @@ protected function configureShowFields(ShowMapper $show): void protected function configureRoutes(RouteCollectionInterface $collection): void { - $collection->clearExcept(['list', 'show', 'delete']); + $collection->add('acknowledge', sprintf('%s/acknowledge', $this->getRouterIdParameter())); + $collection->remove('create'); + $collection->remove('edit'); + } + + protected function configureActionButtons(array $buttonList, string $action, ?object $object = null): array + { + if ('show' === $action && $object?->canBeAcknowledged()) { + $buttonList['acknowledge'] = [ + 'template' => '@DrawSonataIntegration/CronJob/CronJobExecution/show__action_acknowledge.html.twig', + ]; + } + + return $buttonList; } public function configureGridFields(array $fields): array @@ -93,6 +129,7 @@ public function configureGridFields(array $fields): array $fields, [ 'requestedAt' => [], + 'state' => [], 'force' => [], 'executionStartedAt' => [], 'executionEndedAt' => [], diff --git a/packages/sonata-integration-bundle/CronJob/Controller/CronJobController.php b/packages/sonata-integration-bundle/CronJob/Controller/CronJobController.php index 028db644..110e1305 100644 --- a/packages/sonata-integration-bundle/CronJob/Controller/CronJobController.php +++ b/packages/sonata-integration-bundle/CronJob/Controller/CronJobController.php @@ -7,8 +7,8 @@ use Draw\Component\CronJob\CronJobProcessor; use Draw\Component\CronJob\Entity\CronJob; use Sonata\AdminBundle\Controller\CRUDController; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; class CronJobController extends CRUDController { @@ -16,15 +16,12 @@ public function queueAction( Request $request, CronJob $cronJob, CronJobProcessor $cronJobProcessor - ): Response { + ): RedirectResponse { $cronJobProcessor->queue($cronJob, true); $this->addFlash( 'sonata_flash_success', - $this->trans( - 'cron_job_successfully_queued', - domain: 'DrawCronJobSonata' - ) + $this->trans('cron_job_successfully_queued') ); return $this->redirect( diff --git a/packages/sonata-integration-bundle/CronJob/Controller/CronJobExecutionController.php b/packages/sonata-integration-bundle/CronJob/Controller/CronJobExecutionController.php new file mode 100644 index 00000000..ce0ebd42 --- /dev/null +++ b/packages/sonata-integration-bundle/CronJob/Controller/CronJobExecutionController.php @@ -0,0 +1,37 @@ +canBeAcknowledged()) { + $this->addFlash( + 'sonata_flash_error', + $this->trans('cron_job_execution_cannot_be_acknowledged') + ); + + return $this->redirectToList(); + } + + $execution->acknowledge(); + $managerRegistry->getManagerForClass(CronJobExecution::class)->flush(); + + $this->addFlash( + 'sonata_flash_success', + $this->trans('cron_job_execution_successfully_acknowledged') + ); + + return $this->redirectToList(); + } +} diff --git a/packages/sonata-integration-bundle/DependencyInjection/Configuration.php b/packages/sonata-integration-bundle/DependencyInjection/Configuration.php index 40212312..d9a99cc9 100644 --- a/packages/sonata-integration-bundle/DependencyInjection/Configuration.php +++ b/packages/sonata-integration-bundle/DependencyInjection/Configuration.php @@ -7,6 +7,7 @@ use Draw\Bundle\SonataExtraBundle\Configuration\SonataAdminNodeConfiguration; use Draw\Bundle\SonataIntegrationBundle\Console\Controller\ExecutionController; use Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobController; +use Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobExecutionController; use Draw\Bundle\SonataIntegrationBundle\User\Extension\TwoFactorAuthenticationExtension; use Draw\Bundle\UserBundle\DrawUserBundle; use Draw\Bundle\UserBundle\Entity\UserLock; @@ -107,6 +108,7 @@ private function createCronJobNode(): ArrayNodeDefinition (new SonataAdminNodeConfiguration(CronJobExecution::class, 'Cron Job', 'cron_job_execution')) ->addDefaultsIfNotSet() ->pagerTypeDefaultValue('simple') + ->controllerClassDefaultValue(CronJobExecutionController::class) ->labelDefaultValue('Cron Job Execution') ->iconDefaultValue('fas fa-clock') ->translationDomainDefaultValue('DrawCronJobAdmin') diff --git a/packages/sonata-integration-bundle/DependencyInjection/DrawSonataIntegrationExtension.php b/packages/sonata-integration-bundle/DependencyInjection/DrawSonataIntegrationExtension.php index a700ae65..b8865b21 100644 --- a/packages/sonata-integration-bundle/DependencyInjection/DrawSonataIntegrationExtension.php +++ b/packages/sonata-integration-bundle/DependencyInjection/DrawSonataIntegrationExtension.php @@ -135,9 +135,9 @@ private function configureCronJob(array $config, Loader\FileLoader $loader, Cont ) ->setAutowired(true) ->setAutoconfigured(true); - } - $this->setControllerClassDefinition($config['admin']['cron_job'], $container); + $this->setControllerClassDefinition($config['admin'][$adminId], $container); + } } private function configureMessenger(array $config, Loader\FileLoader $loader, ContainerBuilder $container): void diff --git a/packages/sonata-integration-bundle/Resources/translations/DrawCronJobAdmin.en.yaml b/packages/sonata-integration-bundle/Resources/translations/DrawCronJobAdmin.en.yaml new file mode 100644 index 00000000..993dc495 --- /dev/null +++ b/packages/sonata-integration-bundle/Resources/translations/DrawCronJobAdmin.en.yaml @@ -0,0 +1,3 @@ +cron_job_successfully_queued: Cron job successfully queued. +cron_job_execution_successfully_acknowledged: Cron job execution successfully acknowledged. +cron_job_execution_cannot_be_acknowledged: Cron job execution cannot be acknowledged. diff --git a/packages/sonata-integration-bundle/Resources/translations/DrawCronJobSonata.en.yaml b/packages/sonata-integration-bundle/Resources/translations/DrawCronJobSonata.en.yaml deleted file mode 100644 index 700ca6af..00000000 --- a/packages/sonata-integration-bundle/Resources/translations/DrawCronJobSonata.en.yaml +++ /dev/null @@ -1 +0,0 @@ -cron_job_successfully_queued: Cron job successfully queued. diff --git a/packages/sonata-integration-bundle/Resources/views/CronJob/CronJobExecution/list__action_acknowledge.html.twig b/packages/sonata-integration-bundle/Resources/views/CronJob/CronJobExecution/list__action_acknowledge.html.twig new file mode 100644 index 00000000..ab5f1e0b --- /dev/null +++ b/packages/sonata-integration-bundle/Resources/views/CronJob/CronJobExecution/list__action_acknowledge.html.twig @@ -0,0 +1,8 @@ +{% if object.canBeAcknowledged() %} + + Acknowledge + +{% endif %} diff --git a/packages/sonata-integration-bundle/Resources/views/CronJob/CronJobExecution/show__action_acknowledge.html.twig b/packages/sonata-integration-bundle/Resources/views/CronJob/CronJobExecution/show__action_acknowledge.html.twig new file mode 100644 index 00000000..266f53d5 --- /dev/null +++ b/packages/sonata-integration-bundle/Resources/views/CronJob/CronJobExecution/show__action_acknowledge.html.twig @@ -0,0 +1,8 @@ +
  • + + Acknowledge + +
  • diff --git a/packages/sonata-integration-bundle/Tests/DependencyInjection/ConfigurationTest.php b/packages/sonata-integration-bundle/Tests/DependencyInjection/ConfigurationTest.php index 15937f16..f2612bd5 100644 --- a/packages/sonata-integration-bundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/packages/sonata-integration-bundle/Tests/DependencyInjection/ConfigurationTest.php @@ -6,6 +6,7 @@ use App\Sonata\Admin\UserAdmin; use Draw\Bundle\SonataIntegrationBundle\Console\Controller\ExecutionController; use Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobController; +use Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobExecutionController; use Draw\Bundle\SonataIntegrationBundle\DependencyInjection\Configuration; use Draw\Bundle\SonataIntegrationBundle\User\Extension\TwoFactorAuthenticationExtension; use Draw\Bundle\UserBundle\Entity\UserLock; @@ -71,7 +72,7 @@ public function getDefaultConfiguration(): array 'cron_job_execution' => [ 'group' => 'Cron Job', 'entity_class' => CronJobExecution::class, - 'controller_class' => 'sonata.admin.controller.crud', + 'controller_class' => CronJobExecutionController::class, 'icon' => 'fas fa-clock', 'label' => 'Cron Job Execution', 'pager_type' => 'simple', diff --git a/packages/sonata-integration-bundle/Tests/DependencyInjection/DrawSonataIntegrationExtensionCronJobEnabledTest.php b/packages/sonata-integration-bundle/Tests/DependencyInjection/DrawSonataIntegrationExtensionCronJobEnabledTest.php index b2bb8f6e..b41cd170 100644 --- a/packages/sonata-integration-bundle/Tests/DependencyInjection/DrawSonataIntegrationExtensionCronJobEnabledTest.php +++ b/packages/sonata-integration-bundle/Tests/DependencyInjection/DrawSonataIntegrationExtensionCronJobEnabledTest.php @@ -7,6 +7,7 @@ use Draw\Bundle\SonataIntegrationBundle\CronJob\Admin\CronJobAdmin; use Draw\Bundle\SonataIntegrationBundle\CronJob\Admin\CronJobExecutionAdmin; use Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobController; +use Draw\Bundle\SonataIntegrationBundle\CronJob\Controller\CronJobExecutionController; use Draw\Bundle\SonataIntegrationBundle\DependencyInjection\DrawSonataIntegrationExtension; use Draw\Bundle\SonataIntegrationBundle\Tests\DependencyInjection\DrawSonataIntegrationExtensionTest; use PHPUnit\Framework\Attributes\CoversClass; @@ -30,5 +31,6 @@ public static function provideTestHasServiceDefinition(): iterable yield [CronJobAdmin::class]; yield [CronJobExecutionAdmin::class]; yield [CronJobController::class]; + yield [CronJobExecutionController::class]; } }