diff --git a/.phpunit.result.cache b/.phpunit.result.cache new file mode 100644 index 0000000..1a723ec --- /dev/null +++ b/.phpunit.result.cache @@ -0,0 +1 @@ +{"version":1,"defects":{"Drift\\CommandBus\\Tests\\Bus\\QueryHandlerTest::testQueryBus":4,"Drift\\CommandBus\\Tests\\Bus\\QueryHandlerTest::testBusesInjection":5,"Drift\\CommandBus\\Tests\\Bus\\CommandHandlerTest::testBusesInjection":4,"Drift\\CommandBus\\Tests\\Bus\\AsyncCommandHandlerTest::testQueryBus":4},"times":{"Drift\\CommandBus\\Tests\\Bus\\DiscriminableBusTest::testQueryBus":0.003,"Drift\\CommandBus\\Tests\\Bus\\QueryHandlerTest::testQueryBus":0.002,"Drift\\CommandBus\\Tests\\Bus\\QueryHandlerTest::testBadCommand":0,"Drift\\CommandBus\\Tests\\Bus\\QueryHandlerTest::testBusesInjection":0,"Drift\\CommandBus\\Tests\\Bus\\CommandHandlerTest::testQueryBus":0.002,"Drift\\CommandBus\\Tests\\Bus\\CommandHandlerTest::testBusesInjection":0.001,"Drift\\CommandBus\\Tests\\Bus\\AsyncCommandHandlerTest::testQueryBus":0,"Drift\\CommandBus\\Tests\\Bus\\AsyncCommandHandlerTest::testBusesInjection":0.002}} \ No newline at end of file diff --git a/Bus/AsyncCommandBus.php b/Bus/AsyncCommandBus.php new file mode 100644 index 0000000..d7ee6c2 --- /dev/null +++ b/Bus/AsyncCommandBus.php @@ -0,0 +1,23 @@ + + */ + +declare(strict_types=1); + +namespace Drift\CommandBus\Bus; + +/** + * Class AsyncCommandBus. + */ +class AsyncCommandBus extends CommandBus +{ +} diff --git a/DependencyInjection/CompilerPass/BusCompilerPass.php b/DependencyInjection/CompilerPass/BusCompilerPass.php index ad8d97f..2facfac 100644 --- a/DependencyInjection/CompilerPass/BusCompilerPass.php +++ b/DependencyInjection/CompilerPass/BusCompilerPass.php @@ -21,6 +21,7 @@ use Drift\CommandBus\Async\InMemoryAdapter; use Drift\CommandBus\Async\PostgreSQLAdapter; use Drift\CommandBus\Async\RedisAdapter; +use Drift\CommandBus\Bus\AsyncCommandBus; use Drift\CommandBus\Bus\CommandBus; use Drift\CommandBus\Bus\InlineCommandBus; use Drift\CommandBus\Bus\QueryBus; @@ -49,65 +50,106 @@ */ class BusCompilerPass implements CompilerPassInterface { + const BUS_TYPE_COMMAND = 'command'; + const BUS_TYPE_QUERY = 'query'; + /** * {@inheritdoc} */ public function process(ContainerBuilder $container) { - $asyncBus = $this->createAsyncMiddleware($container); - - $this->createQueryHandlerMiddleware($container); - $this->createCommandHandlerMiddleware($container); - $this->createQueryBus($container); - $this->createCommandBus($container, $asyncBus); - $this->createInlineCommandBus($container); - $this->createBusDebugger($container); + $asyncEnabled = static::createAsyncMiddleware($container); + static:: createBuses( + $container, + $asyncEnabled, + $container->getParameter('bus.query_bus.distribution'), + $container->getParameter('bus.query_bus.middlewares'), + $container->getParameter('bus.command_bus.distribution'), + $container->getParameter('bus.command_bus.middlewares') + ); - if ($asyncBus) { - $this->createCommandConsumer($container); - $this->createInfrastructureCreateCommand($container); - $this->createInfrastructureDropCommand($container); - $this->createInfrastructureCheckCommand($container); + if ($asyncEnabled) { + static::createAsyncBuses($container); } } /** - * Check for async middleware needs and return if has been created. - * * @param ContainerBuilder $container + * @param bool $asyncBus + * @param string $queryBusDistribution + * @param array $queryMiddlewares + * @param string $commandBusDistribution + * @param array $commandMiddlewares + */ + public static function createBuses( + ContainerBuilder $container, + bool $asyncBus, + string $queryBusDistribution, + array $queryMiddlewares, + string $commandBusDistribution, + array $commandMiddlewares + ) { + static::createQueryHandlerMiddleware($container); + static::createCommandHandlerMiddleware($container); + static::createQueryBus($container, $queryBusDistribution, $queryMiddlewares); + static::createCommandBus($container, $commandBusDistribution, $commandMiddlewares, $asyncBus); + static::createInlineCommandBus($container, $commandBusDistribution, $commandMiddlewares); + static::createBusDebugger($container); + } + + /** + * @param ContainerBuilder $container + */ + public static function createAsyncBuses(ContainerBuilder $container) + { + static::createCommandConsumer($container); + static::createInfrastructureCreateCommand($container); + static::createInfrastructureDropCommand($container); + static::createInfrastructureCheckCommand($container); + } + + /** + * @param ContainerBuilder $container + * @param array|null $adapter * * @return bool */ - public function createAsyncMiddleware(ContainerBuilder $container): bool - { - $asyncAdapters = $container->getParameter('bus.command_bus.async_adapter'); + public static function createAsyncMiddleware( + ContainerBuilder $container, + array $adapter = null + ): bool { + if (is_array($adapter)) { + $adapterType = $adapter['type']; + } else { + $asyncAdapters = $container->getParameter('bus.command_bus.async_adapter'); + + if ( + empty($asyncAdapters) || + ( + isset($asyncAdapters['adapter']) && + !isset($asyncAdapters[$asyncAdapters['adapter']]) + ) + ) { + return false; + } - if ( - empty($asyncAdapters) || - ( - isset($asyncAdapters['adapter']) && - !isset($asyncAdapters[$asyncAdapters['adapter']]) - ) - ) { - return false; + $adapterType = $asyncAdapters['adapter'] ?? array_key_first($asyncAdapters); + $adapterType = $container->resolveEnvPlaceholders($adapterType, true); + $adapter = $asyncAdapters[$adapterType]; } - $adapterType = $asyncAdapters['adapter'] ?? array_key_first($asyncAdapters); - $adapterType = $container->resolveEnvPlaceholders($adapterType, true); - $adapter = $asyncAdapters[$adapterType]; - switch ($adapterType) { case 'amqp': - $this->createAMQPAsyncAdapter($container, $adapter); + static::createAMQPAsyncAdapter($container, $adapter); break; case 'in_memory': - $this->createInMemoryAsyncAdapter($container); + static::createInMemoryAsyncAdapter($container); break; case 'redis': - $this->createRedisAsyncAdapter($container, $adapter); + static::createRedisAsyncAdapter($container, $adapter); break; case 'postgresql': - $this->createPostgreSQLAsyncAdapter($container, $adapter); + static::createPostgreSQLAsyncAdapter($container, $adapter); break; default: throw new Exception('Wrong adapter. Please use one of this list: amqp, in_memory, redis, postgresql.'); @@ -132,11 +174,11 @@ public function createAsyncMiddleware(ContainerBuilder $container): bool * @throws InvalidMiddlewareException * @throws ReflectionException */ - private function createQueryHandlerMiddleware(ContainerBuilder $container) + private static function createQueryHandlerMiddleware(ContainerBuilder $container) { $handlerMiddlewareId = 'bus.query_bus.handler_middleware'; $handlerMiddleware = new Definition(HandlerMiddleware::class); - $handlerMap = $this->createHandlersMap($container, 'query_handler'); + $handlerMap = static::createHandlersMap($container, 'query_handler'); foreach ($handlerMap as $command => list($reference, $method)) { $handlerMiddleware->addMethodCall('addHandler', [ @@ -155,11 +197,11 @@ private function createQueryHandlerMiddleware(ContainerBuilder $container) * @throws InvalidMiddlewareException * @throws ReflectionException */ - private function createCommandHandlerMiddleware(ContainerBuilder $container) + private static function createCommandHandlerMiddleware(ContainerBuilder $container) { $handlerMiddlewareId = 'bus.command_bus.handler_middleware'; $handlerMiddleware = new Definition(HandlerMiddleware::class); - $handlerMap = $this->createHandlersMap($container, 'command_handler'); + $handlerMap = static::createHandlersMap($container, 'command_handler'); foreach ($handlerMap as $command => list($reference, $method)) { $handlerMiddleware->addMethodCall('addHandler', [ @@ -174,18 +216,24 @@ private function createCommandHandlerMiddleware(ContainerBuilder $container) * Create query bus. * * @param ContainerBuilder $container + * @param string $queryBusDistribution + * @param array $queryMiddlewares */ - private function createQueryBus(ContainerBuilder $container) - { + private static function createQueryBus( + ContainerBuilder $container, + string $queryBusDistribution, + array $queryMiddlewares + ) { $container->setDefinition('drift.query_bus', (new Definition( QueryBus::class, [ new Reference(LoopInterface::class), - $this->createMiddlewaresArray( + static::createMiddlewaresArray( $container, - 'query', - false + $queryMiddlewares, + false, + self::BUS_TYPE_QUERY ), - $container->getParameter('bus.query_bus.distribution'), + $queryBusDistribution, ] )) ->addTag('preload') @@ -199,21 +247,27 @@ private function createQueryBus(ContainerBuilder $container) * Create command bus. * * @param ContainerBuilder $container + * @param string $commandBusDistribution + * @param array $commandMiddlewares * @param bool $asyncBus */ - private function createCommandBus( + private static function createCommandBus( ContainerBuilder $container, + string $commandBusDistribution, + array $commandMiddlewares, bool $asyncBus ) { + $class = $asyncBus ? AsyncCommandBus::class : CommandBus::class; $container->setDefinition('drift.command_bus', (new Definition( - CommandBus::class, [ + $class, [ new Reference(LoopInterface::class), - $this->createMiddlewaresArray( + static::createMiddlewaresArray( $container, - 'command', - $asyncBus + $commandMiddlewares, + $asyncBus, + self::BUS_TYPE_COMMAND ), - $container->getParameter('bus.command_bus.distribution'), + $commandBusDistribution, ] )) ->addTag('preload') @@ -221,24 +275,34 @@ private function createCommandBus( ); $container->setAlias(CommandBus::class, 'drift.command_bus'); + + if ($asyncBus) { + $container->setAlias(AsyncCommandBus::class, 'drift.command_bus'); + } } /** * Create command bus. * * @param ContainerBuilder $container + * @param string $commandBusDistribution + * @param array $commandMiddlewares */ - private function createInlineCommandBus(ContainerBuilder $container) - { + private static function createInlineCommandBus( + ContainerBuilder $container, + string $commandBusDistribution, + array $commandMiddlewares + ) { $container->setDefinition('drift.inline_command_bus', (new Definition( InlineCommandBus::class, [ new Reference(LoopInterface::class), - $this->createMiddlewaresArray( + static::createMiddlewaresArray( $container, - 'command', - false + $commandMiddlewares, + false, + self::BUS_TYPE_COMMAND ), - $container->getParameter('bus.command_bus.distribution'), + $commandBusDistribution, ] )) ->addTag('preload') @@ -249,20 +313,19 @@ private function createInlineCommandBus(ContainerBuilder $container) } /** - * Create array of middlewares by configuration. - * * @param ContainerBuilder $container - * @param string $type + * @param array $definedMiddlewares * @param bool $isAsync + * @param string $type * * @return array */ - private function createMiddlewaresArray( + private static function createMiddlewaresArray( ContainerBuilder $container, - string $type, - bool $isAsync = false + array $definedMiddlewares, + bool $isAsync, + string $type ) { - $definedMiddlewares = $container->getParameter("bus.{$type}_bus.middlewares"); $asyncFound = array_search('@async', $definedMiddlewares); $middlewares = []; @@ -276,7 +339,7 @@ private function createMiddlewaresArray( if ('@async' === $middleware) { if ( true === $isAsync && - 'command' === $type + self::BUS_TYPE_COMMAND === $type ) { $middlewares[] = new Reference(AsyncMiddleware::class); @@ -324,7 +387,7 @@ private function createMiddlewaresArray( * @throws InvalidMiddlewareException * @throws ReflectionException */ - private function createHandlersMap( + private static function createHandlersMap( ContainerBuilder $container, string $tag ): array { @@ -356,7 +419,7 @@ private function createHandlersMap( * * @param ContainerBuilder $container */ - private function createCommandConsumer(ContainerBuilder $container) + private static function createCommandConsumer(ContainerBuilder $container) { $consumer = new Definition(CommandConsumerCommand::class, [ new Reference(AsyncAdapter::class), @@ -376,7 +439,7 @@ private function createCommandConsumer(ContainerBuilder $container) * * @param ContainerBuilder $container */ - private function createBusDebugger(ContainerBuilder $container) + private static function createBusDebugger(ContainerBuilder $container) { $consumer = new Definition(DebugCommandBusCommand::class, [ new Reference('drift.command_bus'), @@ -396,7 +459,7 @@ private function createBusDebugger(ContainerBuilder $container) * * @param ContainerBuilder $container */ - private function createInfrastructureCreateCommand(ContainerBuilder $container) + private static function createInfrastructureCreateCommand(ContainerBuilder $container) { $consumer = new Definition(InfrastructureCreateCommand::class, [ new Reference(AsyncAdapter::class), @@ -415,7 +478,7 @@ private function createInfrastructureCreateCommand(ContainerBuilder $container) * * @param ContainerBuilder $container */ - private function createInfrastructureDropCommand(ContainerBuilder $container) + private static function createInfrastructureDropCommand(ContainerBuilder $container) { $consumer = new Definition(InfrastructureDropCommand::class, [ new Reference(AsyncAdapter::class), @@ -434,7 +497,7 @@ private function createInfrastructureDropCommand(ContainerBuilder $container) * * @param ContainerBuilder $container */ - private function createInfrastructureCheckCommand(ContainerBuilder $container) + private static function createInfrastructureCheckCommand(ContainerBuilder $container) { $consumer = new Definition(InfrastructureCheckCommand::class, [ new Reference(AsyncAdapter::class), @@ -457,7 +520,7 @@ private function createInfrastructureCheckCommand(ContainerBuilder $container) * * @param ContainerBuilder $container */ - private function createInMemoryAsyncAdapter(ContainerBuilder $container) + private static function createInMemoryAsyncAdapter(ContainerBuilder $container) { $container->setDefinition( AsyncAdapter::class, @@ -475,7 +538,7 @@ private function createInMemoryAsyncAdapter(ContainerBuilder $container) * @param ContainerBuilder $container * @param array $adapter */ - private function createRedisAsyncAdapter( + private static function createRedisAsyncAdapter( ContainerBuilder $container, array $adapter ) { @@ -500,7 +563,7 @@ private function createRedisAsyncAdapter( * @param ContainerBuilder $container * @param array $adapter */ - private function createPostgreSQLAsyncAdapter( + private static function createPostgreSQLAsyncAdapter( ContainerBuilder $container, array $adapter ) { @@ -527,7 +590,7 @@ private function createPostgreSQLAsyncAdapter( * @param ContainerBuilder $container * @param array $adapter */ - private function createAMQPAsyncAdapter( + private static function createAMQPAsyncAdapter( ContainerBuilder $container, array $adapter ) { diff --git a/Tests/Async/RedisAsyncTest.php b/Tests/Async/RedisAsyncTest.php index 4d17f0c..f5e5021 100644 --- a/Tests/Async/RedisAsyncTest.php +++ b/Tests/Async/RedisAsyncTest.php @@ -16,9 +16,9 @@ namespace Drift\CommandBus\Tests\Async; /** - * Class RedisAsyncAdapterTest. + * Class RedisAsyncTest. */ -class RedisAsyncAdapterTest extends AsyncAdapterTest +class RedisAsyncTest extends AsyncAdapterTest { /** * {@inheritdoc} diff --git a/Tests/AsyncService.php b/Tests/AsyncService.php new file mode 100644 index 0000000..ffd1fd1 --- /dev/null +++ b/Tests/AsyncService.php @@ -0,0 +1,50 @@ + + */ + +declare(strict_types=1); + +namespace Drift\CommandBus\Tests; + +use Drift\CommandBus\Bus\AsyncCommandBus; +use Drift\CommandBus\Bus\CommandBus; +use Drift\CommandBus\Bus\InlineCommandBus; +use Drift\CommandBus\Bus\QueryBus; + +/** + * Class AsyncService. + */ +class AsyncService +{ + private CommandBus $commandBus; + private AsyncCommandBus $asyncCommandBus; + private InlineCommandBus $inlineCommandBus; + private QueryBus $queryBus; + + /** + * @param CommandBus $commandBus + * @param AsyncCommandBus $asyncCommandBus + * @param InlineCommandBus $inlineCommandBus + * @param QueryBus $queryBus + */ + public function __construct( + CommandBus $commandBus, + AsyncCommandBus $asyncCommandBus, + InlineCommandBus $inlineCommandBus, + QueryBus $queryBus + ) { + $this->commandBus = $commandBus; + $this->asyncCommandBus = $asyncCommandBus; + $this->inlineCommandBus = $inlineCommandBus; + $this->queryBus = $queryBus; + } +} diff --git a/Tests/Bus/AsyncCommandHandlerTest.php b/Tests/Bus/AsyncCommandHandlerTest.php new file mode 100644 index 0000000..de2a696 --- /dev/null +++ b/Tests/Bus/AsyncCommandHandlerTest.php @@ -0,0 +1,65 @@ + + */ + +declare(strict_types=1); + +namespace Drift\CommandBus\Tests\Bus; + +use Drift\CommandBus\Tests\AsyncService; +use Drift\CommandBus\Tests\BusFunctionalTest; +use Drift\CommandBus\Tests\CommandHandler\ChangeAThingHandler; +use Drift\CommandBus\Tests\Context; +use Drift\CommandBus\Tests\Service; + +/** + * Class AsyncCommandHandlerTest. + */ +class AsyncCommandHandlerTest extends BusFunctionalTest +{ + /** + * Decorate configuration. + * + * @param array $configuration + * + * @return array + */ + protected static function decorateConfiguration(array $configuration): array + { + $configuration['services'][AsyncService::class] = []; + $configuration['services'][Service::class] = []; + $configuration['services'][Context::class] = []; + $configuration['services'][ChangeAThingHandler::class] = [ + 'tags' => [ + ['name' => 'command_handler', 'method' => 'handle'], + ['name' => 'another_tag', 'method' => 'anotherMethod'], + ], + ]; + + $configuration['command_bus']['command-bus']['async_adapter'] = [ + 'adapter' => 'in_memory', + 'in_memory' => [], + ]; + + return $configuration; + } + + /** + * Buses injection. + */ + public function testBusesInjection() + { + $this->expectNotToPerformAssertions(); + $this->get(Service::class); + $this->get(AsyncService::class); + } +} diff --git a/Tests/Bus/CommandHandlerTest.php b/Tests/Bus/CommandHandlerTest.php index 9652581..4bfd6fd 100644 --- a/Tests/Bus/CommandHandlerTest.php +++ b/Tests/Bus/CommandHandlerTest.php @@ -22,6 +22,7 @@ use Drift\CommandBus\Tests\Command\ChangeAThing; use Drift\CommandBus\Tests\CommandHandler\ChangeAThingHandler; use Drift\CommandBus\Tests\Context; +use Drift\CommandBus\Tests\Service; /** * Class CommandHandlerTest. @@ -37,6 +38,7 @@ class CommandHandlerTest extends BusFunctionalTest */ protected static function decorateConfiguration(array $configuration): array { + $configuration['services'][Service::class] = []; $configuration['services'][Context::class] = []; $configuration['services'][ChangeAThingHandler::class] = [ 'tags' => [ @@ -91,4 +93,13 @@ public function testQueryBus() ->getMiddlewareList() ); } + + /** + * Buses injection. + */ + public function testBusesInjection() + { + $this->expectNotToPerformAssertions(); + $this->get(Service::class); + } } diff --git a/Tests/Bus/QueryHandlerTest.php b/Tests/Bus/QueryHandlerTest.php index 7e29a46..f7e94d2 100644 --- a/Tests/Bus/QueryHandlerTest.php +++ b/Tests/Bus/QueryHandlerTest.php @@ -22,6 +22,7 @@ use Drift\CommandBus\Tests\Context; use Drift\CommandBus\Tests\Query\GetAThing; use Drift\CommandBus\Tests\QueryHandler\GetAThingHandler; +use Drift\CommandBus\Tests\Service; /** * Class QueryHandlerTest. @@ -37,6 +38,7 @@ class QueryHandlerTest extends BusFunctionalTest */ protected static function decorateConfiguration(array $configuration): array { + $configuration['services'][Service::class] = []; $configuration['services'][Context::class] = []; $configuration['services'][GetAThingHandler::class] = [ 'tags' => [ @@ -89,4 +91,13 @@ public function testBadCommand() await($promise, $this->getLoop()); } + + /** + * Buses injection. + */ + public function testBusesInjection() + { + $this->expectNotToPerformAssertions(); + $this->get(Service::class); + } } diff --git a/Tests/Bus/QueryHandlerWithMiddlewareTest.php b/Tests/Bus/QueryHandlerWithMiddlewareTest.php index 93907ed..5ca935b 100644 --- a/Tests/Bus/QueryHandlerWithMiddlewareTest.php +++ b/Tests/Bus/QueryHandlerWithMiddlewareTest.php @@ -31,7 +31,7 @@ /** * Class QueryHandlerWithMiddleware. */ -class QueryHandlerWithMiddleware extends BusFunctionalTest +class QueryHandlerWithMiddlewareTest extends BusFunctionalTest { /** * Decorate configuration. diff --git a/Tests/Service.php b/Tests/Service.php new file mode 100644 index 0000000..5ed9bf2 --- /dev/null +++ b/Tests/Service.php @@ -0,0 +1,45 @@ + + */ + +declare(strict_types=1); + +namespace Drift\CommandBus\Tests; + +use Drift\CommandBus\Bus\CommandBus; +use Drift\CommandBus\Bus\InlineCommandBus; +use Drift\CommandBus\Bus\QueryBus; + +/** + * Class Service. + */ +class Service +{ + private CommandBus $commandBus; + private InlineCommandBus $inlineCommandBus; + private QueryBus $queryBus; + + /** + * @param CommandBus $commandBus + * @param InlineCommandBus $inlineCommandBus + * @param QueryBus $queryBus + */ + public function __construct( + CommandBus $commandBus, + InlineCommandBus $inlineCommandBus, + QueryBus $queryBus + ) { + $this->commandBus = $commandBus; + $this->inlineCommandBus = $inlineCommandBus; + $this->queryBus = $queryBus; + } +}