diff --git a/.docs/README.md b/.docs/README.md index 9e44aad..4b6225f 100644 --- a/.docs/README.md +++ b/.docs/README.md @@ -18,7 +18,11 @@ config.neon: ```neon extensions: + # Nette 3.0+ rabbitmq: Contributte\RabbitMQ\DI\RabbitMQExtension + + # Nette 2.4 + rabbitmq: Contributte\RabbitMQ\DI\RabbitMQExtension24 ``` ### Example configuration @@ -40,7 +44,7 @@ rabbitmq: testQueue: connection: default # force queue declare on first queue operation during request - # autoCreate: true + # autoCreate: true exchanges: testExchange: @@ -75,7 +79,7 @@ tracy: ### Declaring Queues and Exchanges -Since v3.0, all queues and exchanges are by default declared on demand using the console command: +Since v3.0, all queues and exchanges are by default declared on demand using the console command: ```bash php index.php rabbitmq:declareQueuesAndExchanges @@ -83,12 +87,12 @@ php index.php rabbitmq:declareQueuesAndExchanges It's intended to be a part of the deploy process to make sure all the queues and exchanges are prepared for use. -If you need to override this behavior (for example only declare queues that are used during a request and nothing else), +If you need to override this behavior (for example only declare queues that are used during a request and nothing else), just add the `autoCreate: true` parameter to queue or exchange of your choice. -You may also want to declare the queues and exchanges via rabbitmq management interface or a script but if you fail to -do so, don't run the declare console command and don't specify `autoCreate: true`, exceptions will be thrown -when accessing undeclared queues/exchanges. +You may also want to declare the queues and exchanges via rabbitmq management interface or a script but if you fail to +do so, don't run the declare console command and don't specify `autoCreate: true`, exceptions will be thrown when +accessing undeclared queues/exchanges. ### Publishing messages @@ -201,7 +205,8 @@ final class LongRunningTestQueue ### Consuming messages -Your consumer callback has to return a confirmation that particular message has been acknowledges (or different states - unack, reject). +Your consumer callback has to return a confirmation that particular message has been acknowledges (or different states - +unack, reject). TestConsumer.php @@ -234,7 +239,8 @@ final class TestConsumer implements IConsumer ### Running a consumer trough CLI -There are two consumer commands prepared. `rabbitmq:consumer` wiil consume messages for specified amount of time (in seconds), to run indefinitely skip this parameter. Following command will be consuming messages for one hour: +There are two consumer commands prepared. `rabbitmq:consumer` wiil consume messages for specified amount of time (in +seconds), to run indefinitely skip this parameter. Following command will be consuming messages for one hour: ```bash php index.php rabbitmq:consumer testConsumer 3600 @@ -246,7 +252,6 @@ Following command will be consuming messages indefinitely: php index.php rabbitmq:consumer testConsumer ``` - `rabbitmq:staticConsumer` will consume particular amount of messages. Following example will consume just 20 messages: ```bash diff --git a/.editorconfig b/.editorconfig index 575834a..559fa33 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,6 +11,6 @@ indent_style = tab indent_size = tab tab_width = 4 -[{*.json,*.yml,*.md}] +[{*.yml,*.md}] indent_style = space indent_size = 2 diff --git a/src/DI/Helpers/AbstractHelper.php b/src/DI/Helpers/AbstractHelper.php index 77891bc..9b2eb78 100644 --- a/src/DI/Helpers/AbstractHelper.php +++ b/src/DI/Helpers/AbstractHelper.php @@ -4,7 +4,7 @@ namespace Contributte\RabbitMQ\DI\Helpers; -use Contributte\RabbitMQ\DI\RabbitMQExtension; +use Nette\DI\CompilerExtension; abstract class AbstractHelper { @@ -13,10 +13,10 @@ abstract class AbstractHelper * @var array */ protected array $defaults = []; - protected RabbitMQExtension $extension; + protected CompilerExtension $extension; - public function __construct(RabbitMQExtension $extension) + public function __construct(CompilerExtension $extension) { $this->extension = $extension; } diff --git a/src/DI/RabbitMQExtension24.php b/src/DI/RabbitMQExtension24.php new file mode 100644 index 0000000..d4cb906 --- /dev/null +++ b/src/DI/RabbitMQExtension24.php @@ -0,0 +1,107 @@ + [], + 'queues' => [], + 'exchanges' => [], + 'producers' => [], + 'consumers' => [], + ]; + private ConnectionsHelper $connectionsHelper; + private QueuesHelper $queuesHelper; + private ProducersHelper $producersHelper; + private ExchangesHelper $exchangesHelper; + private ConsumersHelper $consumersHelper; + + + public function __construct() + { + $this->connectionsHelper = new ConnectionsHelper($this); + $this->queuesHelper = new QueuesHelper($this); + $this->exchangesHelper = new ExchangesHelper($this); + $this->producersHelper = new ProducersHelper($this); + $this->consumersHelper = new ConsumersHelper($this); + } + + + /** + * @throws \InvalidArgumentException + */ + public function loadConfiguration(): void + { + $config = $this->validateConfig($this->defaults); + $builder = $this->getContainerBuilder(); + + /** + * Connections + */ + $this->connectionsHelper->setup($builder, $config['connections']); + + /** + * Queues + */ + $this->queuesHelper->setup($builder, $config['queues']); + + /** + * Exchanges + */ + $this->exchangesHelper->setup($builder, $config['exchanges']); + + /** + * Producers + */ + $this->producersHelper->setup($builder, $config['producers']); + + /** + * Consumers + */ + $this->consumersHelper->setup($builder, $config['consumers']); + + /** + * Register Client class + */ + $builder->addDefinition($this->prefix('client')) + ->setFactory(Client::class); + + $this->setupConsoleCommand(); + } + + + public function setupConsoleCommand(): void + { + $builder = $this->getContainerBuilder(); + + $builder->addDefinition($this->prefix('console.consumerCommand')) + ->setFactory(ConsumerCommand::class) + ->setTags(['console.command' => 'rabbitmq:consumer']); + + $builder->addDefinition($this->prefix('console.staticConsumerCommand')) + ->setFactory(StaticConsumerCommand::class) + ->setTags(['console.command' => 'rabbitmq:staticConsumer']); + + $builder->addDefinition($this->prefix('console.declareQueuesExchangesCommand')) + ->setFactory(DeclareQueuesAndExchangesCommand::class) + ->setTags(['console.command' => 'rabbitmq:declareQueuesAndExchanges']); + } +} diff --git a/tests/Cases/DI/RabbitMQExtension24Test.phpt b/tests/Cases/DI/RabbitMQExtension24Test.phpt new file mode 100644 index 0000000..0c00a40 --- /dev/null +++ b/tests/Cases/DI/RabbitMQExtension24Test.phpt @@ -0,0 +1,48 @@ +load(function (Compiler $compiler): void { + $compiler->addExtension('rabbitmq', new RabbitMQExtension24()); + $compiler->addConfig(NeonLoader::load(' + rabbitmq: + connections: + default: + user: guest + password: guest + host: localhost + port: 5672 + lazy: false + ')); + $compiler->addDependencies([__FILE__]); + }, __METHOD__); + + /** @var Container $container */ + $container = new $class(); + + Assert::type(ConnectionFactory::class, $container->getByType(ConnectionFactory::class)); + } + +} + +(new RabbitMQExtension24Test())->run(); diff --git a/tests/Cases/DI/RabbitMQExtensionTest.phpt b/tests/Cases/DI/RabbitMQExtensionTest.phpt new file mode 100644 index 0000000..378b5d2 --- /dev/null +++ b/tests/Cases/DI/RabbitMQExtensionTest.phpt @@ -0,0 +1,48 @@ +load(function (Compiler $compiler): void { + $compiler->addExtension('rabbitmq', new RabbitMQExtension24()); + $compiler->addConfig(NeonLoader::load(' + rabbitmq: + connections: + default: + user: guest + password: guest + host: localhost + port: 5672 + lazy: false + ')); + $compiler->addDependencies([__FILE__]); + }, __METHOD__); + + /** @var Container $container */ + $container = new $class(); + + Assert::type(ConnectionFactory::class, $container->getByType(ConnectionFactory::class)); + } + +} + +(new RabbitMQExtensionTest())->run(); diff --git a/tests/Cases/ProducerTest.phpt b/tests/Cases/ProducerTest.phpt index 5f1b16b..9f486b6 100644 --- a/tests/Cases/ProducerTest.phpt +++ b/tests/Cases/ProducerTest.phpt @@ -295,13 +295,11 @@ final class ProducerTest extends TestCase $channelMock = new ChannelMock(); $connectionMock = \Mockery::mock(IConnection::class) - ->shouldReceive('getChannel')->andReturn($channelMock)->getMock() - ; + ->shouldReceive('getChannel')->andReturn($channelMock)->getMock(); $queueMock = \Mockery::mock(IQueue::class) ->shouldReceive('getConnection')->andReturn($connectionMock)->getMock() - ->shouldReceive('getName')->andReturn($testQueueName)->getMock() - ; + ->shouldReceive('getName')->andReturn($testQueueName)->getMock(); $producer = new Producer( null, @@ -319,13 +317,11 @@ final class ProducerTest extends TestCase $channelMock = new ChannelMock(); $connectionMock = \Mockery::mock(IConnection::class) - ->shouldReceive('getChannel')->andReturn($channelMock)->getMock() - ; + ->shouldReceive('getChannel')->andReturn($channelMock)->getMock(); $exchangeMock = \Mockery::mock(IExchange::class) ->shouldReceive('getConnection')->andReturn($connectionMock)->getMock() - ->shouldReceive('getName')->andReturn($testExchange)->getMock() - ; + ->shouldReceive('getName')->andReturn($testExchange)->getMock(); $producer = new Producer( $exchangeMock, diff --git a/tests/Toolkit/NeonLoader.php b/tests/Toolkit/NeonLoader.php new file mode 100644 index 0000000..2fb593e --- /dev/null +++ b/tests/Toolkit/NeonLoader.php @@ -0,0 +1,21 @@ +process((array) Neon::decode($str)); + } + +}