diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ee683f..5b5041c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +2.2.0 +===== + +* (feature) Add app validator to ensure, that all tasks are properly configured in the routing. + + 2.1.1 ===== diff --git a/composer.json b/composer.json index c45ce3b..eee78bd 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ "php": ">= 8.4", "21torr/bundle-helpers": "^2.3", "21torr/cli": "^1.2.3", + "21torr/hosting": "^4.0", "21torr/snail": "^1.0.0", "doctrine/doctrine-bundle": "^2.14", "doctrine/orm": "^3.3", @@ -22,7 +23,7 @@ "symfony/config": "^7.2", "symfony/console": "^7.2", "symfony/dependency-injection": "^7.2", - "symfony/event-dispatcher-contracts": "^3.5", + "symfony/event-dispatcher": "^7.3", "symfony/http-kernel": "^7.2", "symfony/messenger": "^7.2", "symfony/scheduler": "^7.2", diff --git a/src/App/AppValidator/TaskManagerAppValidator.php b/src/App/AppValidator/TaskManagerAppValidator.php new file mode 100644 index 0000000..1d1cfae --- /dev/null +++ b/src/App/AppValidator/TaskManagerAppValidator.php @@ -0,0 +1,69 @@ +io; + $io->section("Task Manager: Check that all Tasks have Transports"); + + $taskClasses = $this->bundleConfig->taskClasses; + $io->comment(\sprintf( + "Found %d %s:", + \count($taskClasses), + 1 !== \count($taskClasses) ? "tasks" : "task", + )); + + $allHaveSenders = true; + + foreach ($taskClasses as $taskClass) + { + $task = new \ReflectionClass($taskClass)->newInstanceWithoutConstructor(); + $envelope = Envelope::wrap($task); + + $senders = iterator_to_array($this->sendersLocator->getSenders($envelope)); + $taskHasSenders = [] !== $senders; + + $io->writeln(\sprintf( + "• %s ... %s", + $taskClass, + $taskHasSenders ? "ok" : "not mapped", + )); + + $allHaveSenders = $allHaveSenders && $taskHasSenders; + } + + if ($allHaveSenders) + { + $io->success("All tasks configured correctly."); + + return; + } + + $io->error("Not all tasks are configured correctly."); + $event->markAppAsInvalid("Task Manager: not all tasks have routing"); + } +} diff --git a/src/Config/BundleConfig.php b/src/Config/BundleConfig.php index b8201c9..d20a0b8 100644 --- a/src/Config/BundleConfig.php +++ b/src/Config/BundleConfig.php @@ -11,5 +11,7 @@ public function __construct ( public array $sortedQueues, /** @var string[] */ public array $failureTransports = [], + /** @var class-string[] */ + public array $taskClasses = [], ) {} } diff --git a/src/DependencyInjection/AutoDetectFailureTransportsCompilerInterface.php b/src/DependencyInjection/AutoDetectFailureTransportsCompilerPass.php similarity index 92% rename from src/DependencyInjection/AutoDetectFailureTransportsCompilerInterface.php rename to src/DependencyInjection/AutoDetectFailureTransportsCompilerPass.php index dc93240..f894f3e 100644 --- a/src/DependencyInjection/AutoDetectFailureTransportsCompilerInterface.php +++ b/src/DependencyInjection/AutoDetectFailureTransportsCompilerPass.php @@ -9,7 +9,7 @@ /** * Integrates into symfony/messenger, by automatically detecting the failure transports */ -final class AutoDetectFailureTransportsCompilerInterface implements CompilerPassInterface +final class AutoDetectFailureTransportsCompilerPass implements CompilerPassInterface { /** * @inheritDoc diff --git a/src/DependencyInjection/FindTaskClassesCompilerPass.php b/src/DependencyInjection/FindTaskClassesCompilerPass.php new file mode 100644 index 0000000..970d2c0 --- /dev/null +++ b/src/DependencyInjection/FindTaskClassesCompilerPass.php @@ -0,0 +1,44 @@ +findTaggedServiceIds("task-manager.task") as $taskServiceId => $config) + { + $definition = $container->getDefinition($taskServiceId); + $taskFQCN = $definition->getClass(); + + if (null !== $taskFQCN && str_starts_with($taskFQCN, "App\\")) + { + $taskClasses[] = $taskFQCN; + } + + // Remove task service definition, as these must never be a service + // in the actual runtime. We just use the mechanism to collect all + // tasks in the app. + $container->removeDefinition($taskServiceId); + } + + $container->getDefinition(BundleConfig::class) + ->setArgument('$taskClasses', $taskClasses); + } +} diff --git a/src/TaskManagerBundle.php b/src/TaskManagerBundle.php index 49f2972..51833d2 100644 --- a/src/TaskManagerBundle.php +++ b/src/TaskManagerBundle.php @@ -7,9 +7,11 @@ use Symfony\Component\HttpKernel\Bundle\Bundle; use Torr\BundleHelpers\Bundle\ConfigurableBundleExtension; use Torr\TaskManager\Config\BundleConfig; -use Torr\TaskManager\DependencyInjection\AutoDetectFailureTransportsCompilerInterface; +use Torr\TaskManager\DependencyInjection\AutoDetectFailureTransportsCompilerPass; +use Torr\TaskManager\DependencyInjection\FindTaskClassesCompilerPass; use Torr\TaskManager\DependencyInjection\TaskManagerBundleConfiguration; use Torr\TaskManager\Log\LogCleaner; +use Torr\TaskManager\Task\Task; final class TaskManagerBundle extends Bundle { @@ -45,7 +47,12 @@ static function (array $config, ContainerBuilder $container) : void */ public function build (ContainerBuilder $container) : void { - $container->addCompilerPass(new AutoDetectFailureTransportsCompilerInterface()); + $container + ->addCompilerPass(new AutoDetectFailureTransportsCompilerPass()) + ->addCompilerPass(new FindTaskClassesCompilerPass()); + + $container->registerForAutoconfiguration(Task::class) + ->addTag("task-manager.task"); } /**