diff --git a/docs/bundle/config_reference.md b/docs/bundle/config_reference.md index 025078751..a2dc2f0f6 100644 --- a/docs/bundle/config_reference.md +++ b/docs/bundle/config_reference.md @@ -31,9 +31,6 @@ enqueue: redelivered_delay_time: 0 consumption: - # the time in milliseconds queue consumer waits if no message received - idle_timeout: 0 - # the time in milliseconds queue consumer waits for a message (100 ms by default) receive_timeout: 100 job: false diff --git a/docs/bundle/consumption_extension.md b/docs/bundle/consumption_extension.md index 81b49e52f..fb0bcaf0e 100644 --- a/docs/bundle/consumption_extension.md +++ b/docs/bundle/consumption_extension.md @@ -8,20 +8,14 @@ Let's first create an extension itself: // src/AppBundle/Enqueue; namespace AppBundle\Enqueue; -use Enqueue\Consumption\ExtensionInterface; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\PostMessageReceivedExtensionInterface; +use Enqueue\Consumption\Context\PostMessageReceived; -class CountProcessedMessagesExtension implements ExtensionInterface +class CountProcessedMessagesExtension implements PostMessageReceivedExtensionInterface { - use EmptyExtensionTrait; - private $processedMessages = 0; - /** - * {@inheritdoc} - */ - public function onPostReceived(Context $context) + public function onPostMessageReceived(PostMessageReceived $context): void { $this->processedMessages += 1; } diff --git a/pkg/enqueue-bundle/Consumption/Extension/DoctrineClearIdentityMapExtension.php b/pkg/enqueue-bundle/Consumption/Extension/DoctrineClearIdentityMapExtension.php index 9750fb399..3a973d6b2 100644 --- a/pkg/enqueue-bundle/Consumption/Extension/DoctrineClearIdentityMapExtension.php +++ b/pkg/enqueue-bundle/Consumption/Extension/DoctrineClearIdentityMapExtension.php @@ -2,15 +2,12 @@ namespace Enqueue\Bundle\Consumption\Extension; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\MessageReceivedExtensionInterface; use Symfony\Bridge\Doctrine\RegistryInterface; -class DoctrineClearIdentityMapExtension implements ExtensionInterface +class DoctrineClearIdentityMapExtension implements MessageReceivedExtensionInterface { - use EmptyExtensionTrait; - /** * @var RegistryInterface */ @@ -24,10 +21,7 @@ public function __construct(RegistryInterface $registry) $this->registry = $registry; } - /** - * {@inheritdoc} - */ - public function onPreReceived(Context $context) + public function onMessageReceived(MessageReceived $context): void { foreach ($this->registry->getManagers() as $name => $manager) { $context->getLogger()->debug(sprintf( diff --git a/pkg/enqueue-bundle/Consumption/Extension/DoctrinePingConnectionExtension.php b/pkg/enqueue-bundle/Consumption/Extension/DoctrinePingConnectionExtension.php index 5ca804df1..4a789af25 100644 --- a/pkg/enqueue-bundle/Consumption/Extension/DoctrinePingConnectionExtension.php +++ b/pkg/enqueue-bundle/Consumption/Extension/DoctrinePingConnectionExtension.php @@ -3,15 +3,12 @@ namespace Enqueue\Bundle\Consumption\Extension; use Doctrine\DBAL\Connection; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\MessageReceivedExtensionInterface; use Symfony\Bridge\Doctrine\RegistryInterface; -class DoctrinePingConnectionExtension implements ExtensionInterface +class DoctrinePingConnectionExtension implements MessageReceivedExtensionInterface { - use EmptyExtensionTrait; - /** * @var RegistryInterface */ @@ -25,10 +22,7 @@ public function __construct(RegistryInterface $registry) $this->registry = $registry; } - /** - * {@inheritdoc} - */ - public function onPreReceived(Context $context) + public function onMessageReceived(MessageReceived $context): void { /** @var Connection $connection */ foreach ($this->registry->getConnections() as $connection) { diff --git a/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php b/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php index 4329487e9..d925b7e23 100644 --- a/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php +++ b/pkg/enqueue-bundle/DependencyInjection/EnqueueExtension.php @@ -91,8 +91,7 @@ public function load(array $configs, ContainerBuilder $container): void } $container->getDefinition('enqueue.client.default.queue_consumer') - ->replaceArgument(2, $config['consumption']['idle_time']) - ->replaceArgument(3, $config['consumption']['receive_timeout']) + ->replaceArgument(4, $config['consumption']['receive_timeout']) ; } diff --git a/pkg/enqueue-bundle/Resources/config/client.yml b/pkg/enqueue-bundle/Resources/config/client.yml index 2d929ef17..f7960732f 100644 --- a/pkg/enqueue-bundle/Resources/config/client.yml +++ b/pkg/enqueue-bundle/Resources/config/client.yml @@ -68,6 +68,8 @@ services: arguments: - '@enqueue.client.default.context' - '@enqueue.client.default.consumption_extensions' + - [] + - null - ~ - ~ diff --git a/pkg/enqueue-bundle/Tests/Unit/Consumption/Extension/DoctrineClearIdentityMapExtensionTest.php b/pkg/enqueue-bundle/Tests/Unit/Consumption/Extension/DoctrineClearIdentityMapExtensionTest.php index b011abc35..518b40f2d 100644 --- a/pkg/enqueue-bundle/Tests/Unit/Consumption/Extension/DoctrineClearIdentityMapExtensionTest.php +++ b/pkg/enqueue-bundle/Tests/Unit/Consumption/Extension/DoctrineClearIdentityMapExtensionTest.php @@ -4,9 +4,10 @@ use Doctrine\Common\Persistence\ObjectManager; use Enqueue\Bundle\Consumption\Extension\DoctrineClearIdentityMapExtension; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\MessageReceived; use Interop\Queue\Consumer; use Interop\Queue\Context as InteropContext; +use Interop\Queue\Message; use Interop\Queue\Processor; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -42,17 +43,19 @@ public function testShouldClearIdentityMap() ; $extension = new DoctrineClearIdentityMapExtension($registry); - $extension->onPreReceived($context); + $extension->onMessageReceived($context); } - protected function createContext(): Context + protected function createContext(): MessageReceived { - $context = new Context($this->createMock(InteropContext::class)); - $context->setLogger($this->createMock(LoggerInterface::class)); - $context->setConsumer($this->createMock(Consumer::class)); - $context->setProcessor($this->createMock(Processor::class)); - - return $context; + return new MessageReceived( + $this->createMock(InteropContext::class), + $this->createMock(Consumer::class), + $this->createMock(Message::class), + $this->createMock(Processor::class), + 1, + $this->createMock(LoggerInterface::class) + ); } /** diff --git a/pkg/enqueue-bundle/Tests/Unit/Consumption/Extension/DoctrinePingConnectionExtensionTest.php b/pkg/enqueue-bundle/Tests/Unit/Consumption/Extension/DoctrinePingConnectionExtensionTest.php index b93e507cb..d7f16dd57 100644 --- a/pkg/enqueue-bundle/Tests/Unit/Consumption/Extension/DoctrinePingConnectionExtensionTest.php +++ b/pkg/enqueue-bundle/Tests/Unit/Consumption/Extension/DoctrinePingConnectionExtensionTest.php @@ -4,9 +4,10 @@ use Doctrine\DBAL\Connection; use Enqueue\Bundle\Consumption\Extension\DoctrinePingConnectionExtension; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\MessageReceived; use Interop\Queue\Consumer; use Interop\Queue\Context as InteropContext; +use Interop\Queue\Message; use Interop\Queue\Processor; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; @@ -55,7 +56,7 @@ public function testShouldNotReconnectIfConnectionIsOK() ; $extension = new DoctrinePingConnectionExtension($registry); - $extension->onPreReceived($context); + $extension->onMessageReceived($context); } public function testShouldDoesReconnectIfConnectionFailed() @@ -100,7 +101,7 @@ public function testShouldDoesReconnectIfConnectionFailed() ; $extension = new DoctrinePingConnectionExtension($registry); - $extension->onPreReceived($context); + $extension->onMessageReceived($context); } public function testShouldSkipIfConnectionWasNotOpened() @@ -143,17 +144,19 @@ public function testShouldSkipIfConnectionWasNotOpened() ; $extension = new DoctrinePingConnectionExtension($registry); - $extension->onPreReceived($context); + $extension->onMessageReceived($context); } - protected function createContext(): Context + protected function createContext(): MessageReceived { - $context = new Context($this->createMock(InteropContext::class)); - $context->setLogger($this->createMock(LoggerInterface::class)); - $context->setConsumer($this->createMock(Consumer::class)); - $context->setProcessor($this->createMock(Processor::class)); - - return $context; + return new MessageReceived( + $this->createMock(InteropContext::class), + $this->createMock(Consumer::class), + $this->createMock(Message::class), + $this->createMock(Processor::class), + 1, + $this->createMock(LoggerInterface::class) + ); } /** diff --git a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php index f8aab5dd1..823a2ac13 100644 --- a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/ConfigurationTest.php @@ -39,7 +39,6 @@ public function testShouldUseDefaultConfigurationIfNothingIsConfiguredAtAll() $this->assertEquals([ 'transport' => ['dsn' => 'null:'], 'consumption' => [ - 'idle_time' => 0, 'receive_timeout' => 10000, ], 'job' => false, @@ -66,7 +65,6 @@ public function testShouldUseDefaultTransportIfIfTransportIsConfiguredAtAll() $this->assertEquals([ 'transport' => ['dsn' => 'null:'], 'consumption' => [ - 'idle_time' => 0, 'receive_timeout' => 10000, ], 'job' => false, @@ -383,7 +381,6 @@ public function testShouldSetDefaultConfigurationForConsumption() $this->assertArraySubset([ 'consumption' => [ - 'idle_time' => 0, 'receive_timeout' => 10000, ], ], $config); @@ -397,14 +394,12 @@ public function testShouldAllowConfigureConsumption() $config = $processor->processConfiguration($configuration, [[ 'transport' => [], 'consumption' => [ - 'idle_time' => 123, 'receive_timeout' => 456, ], ]]); $this->assertArraySubset([ 'consumption' => [ - 'idle_time' => 123, 'receive_timeout' => 456, ], ], $config); diff --git a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php index 3efacf7bd..8b4ebf7b2 100644 --- a/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php +++ b/pkg/enqueue-bundle/Tests/Unit/DependencyInjection/EnqueueExtensionTest.php @@ -430,21 +430,17 @@ public function testShouldConfigureQueueConsumer() 'transport' => [ ], 'consumption' => [ - 'idle_time' => 123, 'receive_timeout' => 456, ], ]], $container); $def = $container->getDefinition('enqueue.transport.default.queue_consumer'); - $this->assertSame('%enqueue.transport.default.idle_time%', $def->getArgument(2)); - $this->assertSame('%enqueue.transport.default.receive_timeout%', $def->getArgument(3)); + $this->assertSame('%enqueue.transport.default.receive_timeout%', $def->getArgument(4)); - $this->assertSame(123, $container->getParameter('enqueue.transport.default.idle_time')); $this->assertSame(456, $container->getParameter('enqueue.transport.default.receive_timeout')); $def = $container->getDefinition('enqueue.client.default.queue_consumer'); - $this->assertSame(123, $def->getArgument(2)); - $this->assertSame(456, $def->getArgument(3)); + $this->assertSame(456, $def->getArgument(4)); } public function testShouldLoadProcessAutoconfigureChildDefinition() diff --git a/pkg/enqueue/Client/ConsumptionExtension/DelayRedeliveredMessageExtension.php b/pkg/enqueue/Client/ConsumptionExtension/DelayRedeliveredMessageExtension.php index 0977f95b4..77e3bc451 100644 --- a/pkg/enqueue/Client/ConsumptionExtension/DelayRedeliveredMessageExtension.php +++ b/pkg/enqueue/Client/ConsumptionExtension/DelayRedeliveredMessageExtension.php @@ -3,15 +3,12 @@ namespace Enqueue\Client\ConsumptionExtension; use Enqueue\Client\DriverInterface; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\MessageReceivedExtensionInterface; use Enqueue\Consumption\Result; -class DelayRedeliveredMessageExtension implements ExtensionInterface +class DelayRedeliveredMessageExtension implements MessageReceivedExtensionInterface { - use EmptyExtensionTrait; - const PROPERTY_REDELIVER_COUNT = 'enqueue.redelivery_count'; /** @@ -36,12 +33,9 @@ public function __construct(DriverInterface $driver, $delay) $this->delay = $delay; } - /** - * {@inheritdoc} - */ - public function onPreReceived(Context $context) + public function onMessageReceived(MessageReceived $context): void { - $message = $context->getInteropMessage(); + $message = $context->getMessage(); if (false == $message->isRedelivered()) { return; } diff --git a/pkg/enqueue/Client/ConsumptionExtension/ExclusiveCommandExtension.php b/pkg/enqueue/Client/ConsumptionExtension/ExclusiveCommandExtension.php index e9bbbd8e2..a76e49f30 100644 --- a/pkg/enqueue/Client/ConsumptionExtension/ExclusiveCommandExtension.php +++ b/pkg/enqueue/Client/ConsumptionExtension/ExclusiveCommandExtension.php @@ -5,14 +5,11 @@ use Enqueue\Client\Config; use Enqueue\Client\DriverInterface; use Enqueue\Client\Route; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait as ConsumptionEmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface as ConsumptionExtensionInterface; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\MessageReceivedExtensionInterface; -final class ExclusiveCommandExtension implements ConsumptionExtensionInterface +final class ExclusiveCommandExtension implements MessageReceivedExtensionInterface { - use ConsumptionEmptyExtensionTrait; - /** * @var DriverInterface */ @@ -28,11 +25,9 @@ public function __construct(DriverInterface $driver) $this->driver = $driver; } - public function onPreReceived(Context $context) + public function onMessageReceived(MessageReceived $context): void { - $message = $context->getInteropMessage(); - $queue = $context->getInteropQueue(); - + $message = $context->getMessage(); if ($message->getProperty(Config::TOPIC)) { return; } @@ -47,6 +42,7 @@ public function onPreReceived(Context $context) $this->queueToRouteMap = $this->buildMap(); } + $queue = $context->getConsumer()->getQueue(); if (array_key_exists($queue->getQueueName(), $this->queueToRouteMap)) { $context->getLogger()->debug('[ExclusiveCommandExtension] This is a exclusive command queue and client\'s properties are not set. Setting them'); diff --git a/pkg/enqueue/Client/ConsumptionExtension/FlushSpoolProducerExtension.php b/pkg/enqueue/Client/ConsumptionExtension/FlushSpoolProducerExtension.php index efb6848b8..b7e9ca016 100644 --- a/pkg/enqueue/Client/ConsumptionExtension/FlushSpoolProducerExtension.php +++ b/pkg/enqueue/Client/ConsumptionExtension/FlushSpoolProducerExtension.php @@ -3,14 +3,13 @@ namespace Enqueue\Client\ConsumptionExtension; use Enqueue\Client\SpoolProducer; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\End; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\EndExtensionInterface; +use Enqueue\Consumption\PostMessageReceivedExtensionInterface; -class FlushSpoolProducerExtension implements ExtensionInterface +class FlushSpoolProducerExtension implements PostMessageReceivedExtensionInterface, EndExtensionInterface { - use EmptyExtensionTrait; - /** * @var SpoolProducer */ @@ -24,15 +23,12 @@ public function __construct(SpoolProducer $producer) $this->producer = $producer; } - /** - * {@inheritdoc} - */ - public function onPostReceived(Context $context) + public function onPostMessageReceived(PostMessageReceived $context): void { $this->producer->flush(); } - public function onInterrupted(Context $context) + public function onEnd(End $context): void { $this->producer->flush(); } diff --git a/pkg/enqueue/Client/ConsumptionExtension/SetRouterPropertiesExtension.php b/pkg/enqueue/Client/ConsumptionExtension/SetRouterPropertiesExtension.php index ca6a32bf1..16558867e 100644 --- a/pkg/enqueue/Client/ConsumptionExtension/SetRouterPropertiesExtension.php +++ b/pkg/enqueue/Client/ConsumptionExtension/SetRouterPropertiesExtension.php @@ -4,14 +4,11 @@ use Enqueue\Client\Config; use Enqueue\Client\DriverInterface; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\MessageReceivedExtensionInterface; -class SetRouterPropertiesExtension implements ExtensionInterface +class SetRouterPropertiesExtension implements MessageReceivedExtensionInterface { - use EmptyExtensionTrait; - /** * @var DriverInterface */ @@ -25,16 +22,16 @@ public function __construct(DriverInterface $driver) $this->driver = $driver; } - public function onPreReceived(Context $context) + public function onMessageReceived(MessageReceived $context): void { - $message = $context->getInteropMessage(); + $message = $context->getMessage(); if ($message->getProperty(Config::PROCESSOR)) { return; } $config = $this->driver->getConfig(); $queue = $this->driver->createQueue($config->getRouterQueue()); - if ($context->getInteropQueue()->getQueueName() != $queue->getQueueName()) { + if ($context->getConsumer()->getQueue()->getQueueName() != $queue->getQueueName()) { return; } diff --git a/pkg/enqueue/Client/ConsumptionExtension/SetupBrokerExtension.php b/pkg/enqueue/Client/ConsumptionExtension/SetupBrokerExtension.php index 8b6aecbc1..e35580794 100644 --- a/pkg/enqueue/Client/ConsumptionExtension/SetupBrokerExtension.php +++ b/pkg/enqueue/Client/ConsumptionExtension/SetupBrokerExtension.php @@ -3,14 +3,11 @@ namespace Enqueue\Client\ConsumptionExtension; use Enqueue\Client\DriverInterface; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\Start; +use Enqueue\Consumption\StartExtensionInterface; -class SetupBrokerExtension implements ExtensionInterface +class SetupBrokerExtension implements StartExtensionInterface { - use EmptyExtensionTrait; - /** * @var DriverInterface */ @@ -30,10 +27,7 @@ public function __construct(DriverInterface $driver) $this->isDone = false; } - /** - * {@inheritdoc} - */ - public function onStart(Context $context) + public function onStart(Start $context): void { if (false == $this->isDone) { $this->isDone = true; diff --git a/pkg/enqueue/Client/ExtensionInterface.php b/pkg/enqueue/Client/ExtensionInterface.php index 1a6b27d03..a0b413d69 100644 --- a/pkg/enqueue/Client/ExtensionInterface.php +++ b/pkg/enqueue/Client/ExtensionInterface.php @@ -11,14 +11,4 @@ public function onPreSendCommand(PreSend $context): void; public function onDriverPreSend(DriverPreSend $context): void; public function onPostSend(PostSend $context): void; - -// /** -// * @deprecated -// */ -// public function onPreSend($topic, Message $message); -// -// /** -// * @deprecated -// */ -// public function onPostSend($topic, Message $message); } diff --git a/pkg/enqueue/Consumption/BoundProcessor.php b/pkg/enqueue/Consumption/BoundProcessor.php new file mode 100644 index 000000000..54fa3f1bd --- /dev/null +++ b/pkg/enqueue/Consumption/BoundProcessor.php @@ -0,0 +1,35 @@ +queue = $queue; + $this->processor = $processor; + } + + public function getQueue(): Queue + { + return $this->queue; + } + + public function getProcessor(): Processor + { + return $this->processor; + } +} diff --git a/pkg/enqueue/Consumption/ChainExtension.php b/pkg/enqueue/Consumption/ChainExtension.php index ae71f247c..68c4dd1de 100644 --- a/pkg/enqueue/Consumption/ChainExtension.php +++ b/pkg/enqueue/Consumption/ChainExtension.php @@ -2,93 +2,179 @@ namespace Enqueue\Consumption; +use Enqueue\Consumption\Context\End; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\Context\MessageResult; +use Enqueue\Consumption\Context\PostConsume; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\PreConsume; +use Enqueue\Consumption\Context\PreSubscribe; +use Enqueue\Consumption\Context\ProcessorException; +use Enqueue\Consumption\Context\Start; + class ChainExtension implements ExtensionInterface { - use EmptyExtensionTrait; - - /** - * @var ExtensionInterface[] - */ - private $extensions; + private $startExtensions; + private $preSubscribeExtensions; + private $preConsumeExtensions; + private $messageReceivedExtensions; + private $messageResultExtensions; + private $postMessageReceivedExtensions; + private $processorExceptionExtensions; + private $postConsumeExtensions; + private $endExtensions; /** * @param ExtensionInterface[] $extensions */ public function __construct(array $extensions) { - $this->extensions = []; - array_walk($extensions, function (ExtensionInterface $extension) { - $this->extensions[] = $extension; + $this->startExtensions = []; + $this->preSubscribeExtensions = []; + $this->preConsumeExtensions = []; + $this->messageReceivedExtensions = []; + $this->messageResultExtensions = []; + $this->postMessageReceivedExtensions = []; + $this->processorExceptionExtensions = []; + $this->postConsumeExtensions = []; + $this->endExtensions = []; + + array_walk($extensions, function ($extension) { + if ($extension instanceof ExtensionInterface) { + $this->startExtensions[] = $extension; + $this->preSubscribeExtensions[] = $extension; + $this->preConsumeExtensions[] = $extension; + $this->messageReceivedExtensions[] = $extension; + $this->messageResultExtensions[] = $extension; + $this->postMessageReceivedExtensions[] = $extension; + $this->processorExceptionExtensions[] = $extension; + $this->postConsumeExtensions[] = $extension; + $this->endExtensions[] = $extension; + + return; + } + + $extensionValid = false; + if ($extension instanceof StartExtensionInterface) { + $this->startExtensions[] = $extension; + + $extensionValid = true; + } + + if ($extension instanceof PreSubscribeExtensionInterface) { + $this->preSubscribeExtensions[] = $extension; + + $extensionValid = true; + } + + if ($extension instanceof PreConsumeExtensionInterface) { + $this->preConsumeExtensions[] = $extension; + + $extensionValid = true; + } + + if ($extension instanceof MessageReceivedExtensionInterface) { + $this->messageReceivedExtensions[] = $extension; + + $extensionValid = true; + } + + if ($extension instanceof MessageResultExtensionInterface) { + $this->messageResultExtensions[] = $extension; + + $extensionValid = true; + } + + if ($extension instanceof ProcessorExceptionExtensionInterface) { + $this->processorExceptionExtensions[] = $extension; + + $extensionValid = true; + } + + if ($extension instanceof PostMessageReceivedExtensionInterface) { + $this->postMessageReceivedExtensions[] = $extension; + + $extensionValid = true; + } + + if ($extension instanceof PostConsumeExtensionInterface) { + $this->postConsumeExtensions[] = $extension; + + $extensionValid = true; + } + + if ($extension instanceof EndExtensionInterface) { + $this->endExtensions[] = $extension; + + $extensionValid = true; + } + + if (false == $extensionValid) { + throw new \LogicException('Invalid extension given'); + } }); } - /** - * @param Context $context - */ - public function onStart(Context $context) + public function onStart(Start $context): void { - foreach ($this->extensions as $extension) { + foreach ($this->startExtensions as $extension) { $extension->onStart($context); } } - /** - * @param Context $context - */ - public function onBeforeReceive(Context $context) + public function onPreSubscribe(PreSubscribe $context): void { - foreach ($this->extensions as $extension) { - $extension->onBeforeReceive($context); + foreach ($this->preSubscribeExtensions as $extension) { + $extension->onPreSubscribe($context); } } - /** - * @param Context $context - */ - public function onPreReceived(Context $context) + public function onPreConsume(PreConsume $context): void { - foreach ($this->extensions as $extension) { - $extension->onPreReceived($context); + foreach ($this->preConsumeExtensions as $extension) { + $extension->onPreConsume($context); } } - /** - * @param Context $context - */ - public function onResult(Context $context) + public function onMessageReceived(MessageReceived $context): void { - foreach ($this->extensions as $extension) { + foreach ($this->messageReceivedExtensions as $extension) { + $extension->onMessageReceived($context); + } + } + + public function onResult(MessageResult $context): void + { + foreach ($this->messageResultExtensions as $extension) { $extension->onResult($context); } } - /** - * @param Context $context - */ - public function onPostReceived(Context $context) + public function onProcessorException(ProcessorException $context): void { - foreach ($this->extensions as $extension) { - $extension->onPostReceived($context); + foreach ($this->processorExceptionExtensions as $extension) { + $extension->onProcessorException($context); } } - /** - * @param Context $context - */ - public function onIdle(Context $context) + public function onPostMessageReceived(PostMessageReceived $context): void { - foreach ($this->extensions as $extension) { - $extension->onIdle($context); + foreach ($this->postMessageReceivedExtensions as $extension) { + $extension->onPostMessageReceived($context); } } - /** - * @param Context $context - */ - public function onInterrupted(Context $context) + public function onPostConsume(PostConsume $context): void + { + foreach ($this->postConsumeExtensions as $extension) { + $extension->onPostConsume($context); + } + } + + public function onEnd(End $context): void { - foreach ($this->extensions as $extension) { - $extension->onInterrupted($context); + foreach ($this->endExtensions as $extension) { + $extension->onEnd($context); } } } diff --git a/pkg/enqueue/Consumption/Context.php b/pkg/enqueue/Consumption/Context.php deleted file mode 100644 index 76935c1fd..000000000 --- a/pkg/enqueue/Consumption/Context.php +++ /dev/null @@ -1,233 +0,0 @@ -context = $interopContext; - - $this->executionInterrupted = false; - } - - /** - * @return InteropMessage - */ - public function getInteropMessage() - { - return $this->interopMessage; - } - - /** - * @param InteropMessage $interopMessage - */ - public function setInteropMessage(InteropMessage $interopMessage) - { - if ($this->interopMessage) { - throw new IllegalContextModificationException('The message could be set once'); - } - - $this->interopMessage = $interopMessage; - } - - /** - * @return InteropContext - */ - public function getInteropContext() - { - return $this->context; - } - - /** - * @return Consumer - */ - public function getConsumer() - { - return $this->consumer; - } - - /** - * @param Consumer $consumer - */ - public function setConsumer(Consumer $consumer) - { - if ($this->consumer) { - throw new IllegalContextModificationException('The message consumer could be set once'); - } - - $this->consumer = $consumer; - } - - /** - * @return Processor - */ - public function getProcessor() - { - return $this->processor; - } - - /** - * @param Processor $processor - */ - public function setProcessor(Processor $processor) - { - if ($this->processor) { - throw new IllegalContextModificationException('The message processor could be set once'); - } - - $this->processor = $processor; - } - - /** - * @return \Throwable - */ - public function getException() - { - return $this->exception; - } - - /** - * @param \Throwable $exception - */ - public function setException(\Throwable $exception) - { - $this->exception = $exception; - } - - /** - * @return Result|string - */ - public function getResult() - { - return $this->result; - } - - /** - * @param Result|string $result - */ - public function setResult($result) - { - if ($this->result) { - throw new IllegalContextModificationException('The result modification is not allowed'); - } - - $this->result = $result; - } - - /** - * @return bool - */ - public function isExecutionInterrupted() - { - return $this->executionInterrupted; - } - - /** - * @param bool $executionInterrupted - */ - public function setExecutionInterrupted($executionInterrupted) - { - if (false == $executionInterrupted && $this->executionInterrupted) { - throw new IllegalContextModificationException('The execution once interrupted could not be roll backed'); - } - - $this->executionInterrupted = $executionInterrupted; - } - - /** - * @return LoggerInterface - */ - public function getLogger() - { - return $this->logger; - } - - /** - * @param LoggerInterface $logger - */ - public function setLogger(LoggerInterface $logger) - { - if ($this->logger) { - throw new IllegalContextModificationException('The logger modification is not allowed'); - } - - $this->logger = $logger; - } - - /** - * @return InteropQueue - */ - public function getInteropQueue() - { - return $this->InteropQueue; - } - - /** - * @param InteropQueue $InteropQueue - */ - public function setInteropQueue(InteropQueue $InteropQueue) - { - if ($this->InteropQueue) { - throw new IllegalContextModificationException('The queue modification is not allowed'); - } - - $this->InteropQueue = $InteropQueue; - } -} diff --git a/pkg/enqueue/Consumption/Context/End.php b/pkg/enqueue/Consumption/Context/End.php new file mode 100644 index 000000000..467f6d38c --- /dev/null +++ b/pkg/enqueue/Consumption/Context/End.php @@ -0,0 +1,63 @@ +context = $context; + $this->logger = $logger; + $this->startTime = $startTime; + $this->endTime = $endTime; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getLogger(): LoggerInterface + { + return $this->logger; + } + + /** + * In milliseconds. + */ + public function getStartTime(): int + { + return $this->startTime; + } + + /** + * In milliseconds. + */ + public function getEndTime(): int + { + return $this->startTime; + } +} diff --git a/pkg/enqueue/Consumption/Context/MessageReceived.php b/pkg/enqueue/Consumption/Context/MessageReceived.php new file mode 100644 index 000000000..ad6b6b969 --- /dev/null +++ b/pkg/enqueue/Consumption/Context/MessageReceived.php @@ -0,0 +1,109 @@ +context = $context; + $this->consumer = $consumer; + $this->message = $message; + $this->processor = $processor; + $this->receivedAt = $receivedAt; + $this->logger = $logger; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getConsumer(): Consumer + { + return $this->consumer; + } + + public function getMessage(): Message + { + return $this->message; + } + + public function getProcessor(): Processor + { + return $this->processor; + } + + public function changeProcessor(Processor $processor): void + { + $this->processor = $processor; + } + + public function getLogger(): LoggerInterface + { + return $this->logger; + } + + public function getReceivedAt(): int + { + return $this->receivedAt; + } + + public function getResult(): ?Result + { + return $this->result; + } + + public function setResult(Result $result): void + { + $this->result = $result; + } +} diff --git a/pkg/enqueue/Consumption/Context/MessageResult.php b/pkg/enqueue/Consumption/Context/MessageResult.php new file mode 100644 index 000000000..fccda66b2 --- /dev/null +++ b/pkg/enqueue/Consumption/Context/MessageResult.php @@ -0,0 +1,81 @@ +context = $context; + $this->message = $message; + $this->logger = $logger; + $this->result = $result; + $this->receivedAt = $receivedAt; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getMessage(): Message + { + return $this->message; + } + + public function getLogger(): LoggerInterface + { + return $this->logger; + } + + public function getReceivedAt(): int + { + return $this->receivedAt; + } + + /** + * @return Result|null|object|string + */ + public function getResult() + { + return $this->result; + } + + /** + * @param Result|string|object|null $result + */ + public function changeResult($result): void + { + $this->result = $result; + } +} diff --git a/pkg/enqueue/Consumption/Context/PostConsume.php b/pkg/enqueue/Consumption/Context/PostConsume.php new file mode 100644 index 000000000..0add00336 --- /dev/null +++ b/pkg/enqueue/Consumption/Context/PostConsume.php @@ -0,0 +1,97 @@ +context = $context; + $this->subscriptionConsumer = $subscriptionConsumer; + $this->receivedMessagesCount = $receivedMessagesCount; + $this->cycle = $cycle; + $this->startTime = $startTime; + $this->logger = $logger; + + $this->executionInterrupted = false; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getSubscriptionConsumer(): SubscriptionConsumer + { + return $this->subscriptionConsumer; + } + + public function getReceivedMessagesCount(): int + { + return $this->receivedMessagesCount; + } + + public function getCycle(): int + { + return $this->cycle; + } + + public function getStartTime(): int + { + return $this->startTime; + } + + public function getLogger(): LoggerInterface + { + return $this->logger; + } + + public function isExecutionInterrupted(): bool + { + return $this->executionInterrupted; + } + + public function interruptExecution(): void + { + $this->executionInterrupted = true; + } +} diff --git a/pkg/enqueue/Consumption/Context/PostMessageReceived.php b/pkg/enqueue/Consumption/Context/PostMessageReceived.php new file mode 100644 index 000000000..85ecaecb7 --- /dev/null +++ b/pkg/enqueue/Consumption/Context/PostMessageReceived.php @@ -0,0 +1,95 @@ +context = $context; + $this->message = $message; + $this->result = $result; + $this->receivedAt = $receivedAt; + $this->logger = $logger; + + $this->executionInterrupted = false; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getMessage(): Message + { + return $this->message; + } + + public function getLogger(): LoggerInterface + { + return $this->logger; + } + + public function getReceivedAt(): int + { + return $this->receivedAt; + } + + /** + * @return Result|null|object|string + */ + public function getResult() + { + return $this->result; + } + + public function isExecutionInterrupted(): bool + { + return $this->executionInterrupted; + } + + public function interruptExecution(): void + { + $this->executionInterrupted = true; + } +} diff --git a/pkg/enqueue/Consumption/Context/PreConsume.php b/pkg/enqueue/Consumption/Context/PreConsume.php new file mode 100644 index 000000000..a6d83d534 --- /dev/null +++ b/pkg/enqueue/Consumption/Context/PreConsume.php @@ -0,0 +1,97 @@ +context = $context; + $this->subscriptionConsumer = $subscriptionConsumer; + $this->logger = $logger; + $this->cycle = $cycle; + $this->receiveTimeout = $receiveTimeout; + $this->startTime = $startTime; + + $this->executionInterrupted = false; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getSubscriptionConsumer(): SubscriptionConsumer + { + return $this->subscriptionConsumer; + } + + public function getLogger(): LoggerInterface + { + return $this->logger; + } + + public function getCycle(): int + { + return $this->cycle; + } + + public function getReceiveTimeout(): int + { + return $this->receiveTimeout; + } + + public function getStartTime(): int + { + return $this->startTime; + } + + public function isExecutionInterrupted(): bool + { + return $this->executionInterrupted; + } + + public function interruptExecution(): void + { + $this->executionInterrupted = true; + } +} diff --git a/pkg/enqueue/Consumption/Context/PreSubscribe.php b/pkg/enqueue/Consumption/Context/PreSubscribe.php new file mode 100644 index 000000000..dbc74bb69 --- /dev/null +++ b/pkg/enqueue/Consumption/Context/PreSubscribe.php @@ -0,0 +1,59 @@ +context = $context; + $this->processor = $processor; + $this->consumer = $consumer; + $this->logger = $logger; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getProcessor(): Processor + { + return $this->processor; + } + + public function getConsumer(): Consumer + { + return $this->consumer; + } + + public function getLogger(): LoggerInterface + { + return $this->logger; + } +} diff --git a/pkg/enqueue/Consumption/Context/ProcessorException.php b/pkg/enqueue/Consumption/Context/ProcessorException.php new file mode 100644 index 000000000..139bd6704 --- /dev/null +++ b/pkg/enqueue/Consumption/Context/ProcessorException.php @@ -0,0 +1,84 @@ +context = $context; + $this->message = $message; + $this->exception = $exception; + $this->logger = $logger; + $this->receivedAt = $receivedAt; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getMessage(): Message + { + return $this->message; + } + + public function getException(): \Exception + { + return $this->exception; + } + + public function getLogger(): LoggerInterface + { + return $this->logger; + } + + public function getReceivedAt(): int + { + return $this->receivedAt; + } + + public function getResult(): ?Result + { + return $this->result; + } + + public function setResult(Result $result): void + { + $this->result = $result; + } +} diff --git a/pkg/enqueue/Consumption/Context/Start.php b/pkg/enqueue/Consumption/Context/Start.php new file mode 100644 index 000000000..d1a7be375 --- /dev/null +++ b/pkg/enqueue/Consumption/Context/Start.php @@ -0,0 +1,122 @@ +context = $context; + $this->logger = $logger; + $this->processors = $processors; + $this->receiveTimeout = $receiveTimeout; + $this->startTime = $startTime; + + $this->executionInterrupted = false; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getLogger(): LoggerInterface + { + return $this->logger; + } + + public function changeLogger(LoggerInterface $logger): void + { + $this->logger = $logger; + } + + /** + * In milliseconds. + */ + public function getReceiveTimeout(): int + { + return $this->receiveTimeout; + } + + /** + * In milliseconds. + */ + public function changeReceiveTimeout(int $timeout): void + { + $this->receiveTimeout = $timeout; + } + + /** + * In milliseconds. + */ + public function getStartTime(): int + { + return $this->startTime; + } + + /** + * @return BoundProcessor[] + */ + public function getBoundProcessors(): array + { + return $this->processors; + } + + /** + * @param BoundProcessor[] $processors + */ + public function changeBoundProcessors(array $processors): void + { + $this->processors = []; + array_walk($processors, function (BoundProcessor $processor) { + $this->processors[] = $processor; + }); + } + + public function isExecutionInterrupted(): bool + { + return $this->executionInterrupted; + } + + public function interruptExecution(): void + { + $this->executionInterrupted = true; + } +} diff --git a/pkg/enqueue/Consumption/EmptyExtensionTrait.php b/pkg/enqueue/Consumption/EmptyExtensionTrait.php deleted file mode 100644 index 0f6b849c4..000000000 --- a/pkg/enqueue/Consumption/EmptyExtensionTrait.php +++ /dev/null @@ -1,55 +0,0 @@ -messageLimit = $messageLimit; $this->messageConsumed = 0; } - /** - * {@inheritdoc} - */ - public function onBeforeReceive(Context $context) + public function onPreConsume(PreConsume $context): void { // this is added here to handle an edge case. when a user sets zero as limit. - $this->checkMessageLimit($context); + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); + } } - /** - * {@inheritdoc} - */ - public function onPostReceived(Context $context) + public function onPostMessageReceived(PostMessageReceived $context): void { ++$this->messageConsumed; - $this->checkMessageLimit($context); + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); + } } - /** - * @param Context $context - */ - protected function checkMessageLimit(Context $context) + protected function shouldBeStopped(LoggerInterface $logger): bool { if ($this->messageConsumed >= $this->messageLimit) { - $context->getLogger()->debug(sprintf( + $logger->debug(sprintf( '[LimitConsumedMessagesExtension] Message consumption is interrupted since the message limit reached.'. ' limit: "%s"', $this->messageLimit )); - $context->setExecutionInterrupted(true); + return true; } + + return false; } } diff --git a/pkg/enqueue/Consumption/Extension/LimitConsumerMemoryExtension.php b/pkg/enqueue/Consumption/Extension/LimitConsumerMemoryExtension.php index c03686f33..13d4a2898 100644 --- a/pkg/enqueue/Consumption/Extension/LimitConsumerMemoryExtension.php +++ b/pkg/enqueue/Consumption/Extension/LimitConsumerMemoryExtension.php @@ -2,14 +2,16 @@ namespace Enqueue\Consumption\Extension; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\PostConsume; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\PreConsume; +use Enqueue\Consumption\PostConsumeExtensionInterface; +use Enqueue\Consumption\PostMessageReceivedExtensionInterface; +use Enqueue\Consumption\PreConsumeExtensionInterface; +use Psr\Log\LoggerInterface; -class LimitConsumerMemoryExtension implements ExtensionInterface +class LimitConsumerMemoryExtension implements PreConsumeExtensionInterface, PostMessageReceivedExtensionInterface, PostConsumeExtensionInterface { - use EmptyExtensionTrait; - /** * @var int */ @@ -30,44 +32,40 @@ public function __construct($memoryLimit) $this->memoryLimit = $memoryLimit * 1024 * 1024; } - /** - * {@inheritdoc} - */ - public function onBeforeReceive(Context $context) + public function onPreConsume(PreConsume $context): void { - $this->checkMemory($context); + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); + } } - /** - * {@inheritdoc} - */ - public function onPostReceived(Context $context) + public function onPostMessageReceived(PostMessageReceived $context): void { - $this->checkMemory($context); + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); + } } - /** - * {@inheritdoc} - */ - public function onIdle(Context $context) + public function onPostConsume(PostConsume $context): void { - $this->checkMemory($context); + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); + } } - /** - * @param Context $context - */ - protected function checkMemory(Context $context) + protected function shouldBeStopped(LoggerInterface $logger): bool { $memoryUsage = memory_get_usage(true); if ($memoryUsage >= $this->memoryLimit) { - $context->getLogger()->debug(sprintf( + $logger->debug(sprintf( '[LimitConsumerMemoryExtension] Interrupt execution as memory limit reached. limit: "%s", used: "%s"', $this->memoryLimit, $memoryUsage )); - $context->setExecutionInterrupted(true); + return true; } + + return false; } } diff --git a/pkg/enqueue/Consumption/Extension/LimitConsumptionTimeExtension.php b/pkg/enqueue/Consumption/Extension/LimitConsumptionTimeExtension.php index 65221f5c0..f0a577930 100644 --- a/pkg/enqueue/Consumption/Extension/LimitConsumptionTimeExtension.php +++ b/pkg/enqueue/Consumption/Extension/LimitConsumptionTimeExtension.php @@ -2,14 +2,16 @@ namespace Enqueue\Consumption\Extension; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\PostConsume; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\PreConsume; +use Enqueue\Consumption\PostConsumeExtensionInterface; +use Enqueue\Consumption\PostMessageReceivedExtensionInterface; +use Enqueue\Consumption\PreConsumeExtensionInterface; +use Psr\Log\LoggerInterface; -class LimitConsumptionTimeExtension implements ExtensionInterface +class LimitConsumptionTimeExtension implements PreConsumeExtensionInterface, PostConsumeExtensionInterface, PostMessageReceivedExtensionInterface { - use EmptyExtensionTrait; - /** * @var \DateTime */ @@ -23,45 +25,41 @@ public function __construct(\DateTime $timeLimit) $this->timeLimit = $timeLimit; } - /** - * {@inheritdoc} - */ - public function onBeforeReceive(Context $context) + public function onPreConsume(PreConsume $context): void { - $this->checkTime($context); + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); + } } - /** - * {@inheritdoc} - */ - public function onIdle(Context $context) + public function onPostConsume(PostConsume $context): void { - $this->checkTime($context); + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); + } } - /** - * {@inheritdoc} - */ - public function onPostReceived(Context $context) + public function onPostMessageReceived(PostMessageReceived $context): void { - $this->checkTime($context); + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); + } } - /** - * @param Context $context - */ - protected function checkTime(Context $context) + protected function shouldBeStopped(LoggerInterface $logger): bool { $now = new \DateTime(); if ($now >= $this->timeLimit) { - $context->getLogger()->debug(sprintf( + $logger->debug(sprintf( '[LimitConsumptionTimeExtension] Execution interrupted as limit time has passed.'. ' now: "%s", time-limit: "%s"', $now->format(DATE_ISO8601), $this->timeLimit->format(DATE_ISO8601) )); - $context->setExecutionInterrupted(true); + return true; } + + return false; } } diff --git a/pkg/enqueue/Consumption/Extension/LoggerExtension.php b/pkg/enqueue/Consumption/Extension/LoggerExtension.php index b498e213d..a240a1263 100644 --- a/pkg/enqueue/Consumption/Extension/LoggerExtension.php +++ b/pkg/enqueue/Consumption/Extension/LoggerExtension.php @@ -2,17 +2,17 @@ namespace Enqueue\Consumption\Extension; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\Start; +use Enqueue\Consumption\PostMessageReceivedExtensionInterface; use Enqueue\Consumption\Result; +use Enqueue\Consumption\StartExtensionInterface; use Interop\Queue\Message as InteropMessage; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; -class LoggerExtension implements ExtensionInterface +class LoggerExtension implements StartExtensionInterface, PostMessageReceivedExtensionInterface { - use EmptyExtensionTrait; - /** * @var LoggerInterface */ @@ -26,27 +26,21 @@ public function __construct(LoggerInterface $logger) $this->logger = $logger; } - /** - * {@inheritdoc} - */ - public function onStart(Context $context) + public function onStart(Start $context): void { - if ($context->getLogger()) { + if ($context->getLogger() && false == $context->getLogger() instanceof NullLogger) { $context->getLogger()->debug(sprintf( 'Skip setting context\'s logger "%s". Another one "%s" has already been set.', get_class($this->logger), get_class($context->getLogger()) )); } else { - $context->setLogger($this->logger); + $context->changeLogger($this->logger); $this->logger->debug(sprintf('Set context\'s logger "%s"', get_class($this->logger))); } } - /** - * {@inheritdoc} - */ - public function onPostReceived(Context $context) + public function onPostMessageReceived(PostMessageReceived $context): void { if (false == $context->getResult() instanceof Result) { return; @@ -59,13 +53,13 @@ public function onPostReceived(Context $context) case Result::REJECT: case Result::REQUEUE: if ($result->getReason()) { - $this->logger->error($result->getReason(), $this->messageToLogContext($context->getInteropMessage())); + $this->logger->error($result->getReason(), $this->messageToLogContext($context->getMessage())); } break; case Result::ACK: if ($result->getReason()) { - $this->logger->info($result->getReason(), $this->messageToLogContext($context->getInteropMessage())); + $this->logger->info($result->getReason(), $this->messageToLogContext($context->getMessage())); } break; diff --git a/pkg/enqueue/Consumption/Extension/NicenessExtension.php b/pkg/enqueue/Consumption/Extension/NicenessExtension.php index 01a5383a2..983e04b0e 100644 --- a/pkg/enqueue/Consumption/Extension/NicenessExtension.php +++ b/pkg/enqueue/Consumption/Extension/NicenessExtension.php @@ -2,14 +2,11 @@ namespace Enqueue\Consumption\Extension; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\Start; +use Enqueue\Consumption\StartExtensionInterface; -class NicenessExtension implements ExtensionInterface +class NicenessExtension implements StartExtensionInterface { - use EmptyExtensionTrait; - /** * @var int */ @@ -32,10 +29,7 @@ public function __construct($niceness) $this->niceness = $niceness; } - /** - * {@inheritdoc} - */ - public function onStart(Context $context) + public function onStart(Start $context): void { if (0 !== $this->niceness) { $changed = @proc_nice($this->niceness); diff --git a/pkg/enqueue/Consumption/Extension/ReplyExtension.php b/pkg/enqueue/Consumption/Extension/ReplyExtension.php index 4435e5573..c1ac19bd7 100644 --- a/pkg/enqueue/Consumption/Extension/ReplyExtension.php +++ b/pkg/enqueue/Consumption/Extension/ReplyExtension.php @@ -2,21 +2,15 @@ namespace Enqueue\Consumption\Extension; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\PostMessageReceivedExtensionInterface; use Enqueue\Consumption\Result; -class ReplyExtension implements ExtensionInterface +class ReplyExtension implements PostMessageReceivedExtensionInterface { - use EmptyExtensionTrait; - - /** - * {@inheritdoc} - */ - public function onPostReceived(Context $context) + public function onPostMessageReceived(PostMessageReceived $context): void { - $replyTo = $context->getInteropMessage()->getReplyTo(); + $replyTo = $context->getMessage()->getReplyTo(); if (false == $replyTo) { return; } @@ -31,13 +25,13 @@ public function onPostReceived(Context $context) return; } - $correlationId = $context->getInteropMessage()->getCorrelationId(); + $correlationId = $context->getMessage()->getCorrelationId(); $replyMessage = clone $result->getReply(); $replyMessage->setCorrelationId($correlationId); - $replyQueue = $context->getInteropContext()->createQueue($replyTo); + $replyQueue = $context->getContext()->createQueue($replyTo); $context->getLogger()->debug(sprintf('[ReplyExtension] Send reply to "%s"', $replyTo)); - $context->getInteropContext()->createProducer()->send($replyQueue, $replyMessage); + $context->getContext()->createProducer()->send($replyQueue, $replyMessage); } } diff --git a/pkg/enqueue/Consumption/Extension/SignalExtension.php b/pkg/enqueue/Consumption/Extension/SignalExtension.php index a8b53e8b8..67354b99d 100644 --- a/pkg/enqueue/Consumption/Extension/SignalExtension.php +++ b/pkg/enqueue/Consumption/Extension/SignalExtension.php @@ -2,16 +2,19 @@ namespace Enqueue\Consumption\Extension; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; +use Enqueue\Consumption\Context\PostConsume; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\PreConsume; +use Enqueue\Consumption\Context\Start; use Enqueue\Consumption\Exception\LogicException; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\PostConsumeExtensionInterface; +use Enqueue\Consumption\PostMessageReceivedExtensionInterface; +use Enqueue\Consumption\PreConsumeExtensionInterface; +use Enqueue\Consumption\StartExtensionInterface; use Psr\Log\LoggerInterface; -class SignalExtension implements ExtensionInterface +class SignalExtension implements StartExtensionInterface, PreConsumeExtensionInterface, PostMessageReceivedExtensionInterface, PostConsumeExtensionInterface { - use EmptyExtensionTrait; - /** * @var bool */ @@ -22,86 +25,46 @@ class SignalExtension implements ExtensionInterface */ protected $logger; - /** - * {@inheritdoc} - */ - public function onStart(Context $context) + public function onStart(Start $context): void { if (false == extension_loaded('pcntl')) { throw new LogicException('The pcntl extension is required in order to catch signals.'); } - if (function_exists('pcntl_async_signals')) { - pcntl_async_signals(true); - } + pcntl_async_signals(true); pcntl_signal(SIGTERM, [$this, 'handleSignal']); pcntl_signal(SIGQUIT, [$this, 'handleSignal']); pcntl_signal(SIGINT, [$this, 'handleSignal']); + $this->logger = $context->getLogger(); $this->interruptConsumption = false; } - /** - * @param Context $context - */ - public function onBeforeReceive(Context $context) + public function onPreConsume(PreConsume $context): void { $this->logger = $context->getLogger(); - $this->dispatchSignal(); - - $this->interruptExecutionIfNeeded($context); - } - - /** - * {@inheritdoc} - */ - public function onPreReceived(Context $context) - { - $this->interruptExecutionIfNeeded($context); - } - - /** - * {@inheritdoc} - */ - public function onPostReceived(Context $context) - { - $this->dispatchSignal(); - - $this->interruptExecutionIfNeeded($context); + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); + } } - /** - * {@inheritdoc} - */ - public function onIdle(Context $context) + public function onPostMessageReceived(PostMessageReceived $context): void { - $this->dispatchSignal(); - - $this->interruptExecutionIfNeeded($context); + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); + } } - /** - * @param Context $context - */ - public function interruptExecutionIfNeeded(Context $context) + public function onPostConsume(PostConsume $context): void { - if (false == $context->isExecutionInterrupted() && $this->interruptConsumption) { - if ($this->logger) { - $this->logger->debug('[SignalExtension] Interrupt execution'); - } - - $context->setExecutionInterrupted($this->interruptConsumption); - - $this->interruptConsumption = false; + if ($this->shouldBeStopped($context->getLogger())) { + $context->interruptExecution(); } } - /** - * @param int $signal - */ - public function handleSignal($signal) + public function handleSignal(int $signal): void { if ($this->logger) { $this->logger->debug(sprintf('[SignalExtension] Caught signal: %s', $signal)); @@ -122,10 +85,16 @@ public function handleSignal($signal) } } - private function dispatchSignal() + private function shouldBeStopped(LoggerInterface $logger): bool { - if (false == function_exists('pcntl_async_signals')) { - pcntl_signal_dispatch(); + if ($this->interruptConsumption) { + $logger->debug('[SignalExtension] Interrupt execution'); + + $this->interruptConsumption = false; + + return true; } + + return false; } } diff --git a/pkg/enqueue/Consumption/ExtensionInterface.php b/pkg/enqueue/Consumption/ExtensionInterface.php index 2a5d7bb72..b9280241d 100644 --- a/pkg/enqueue/Consumption/ExtensionInterface.php +++ b/pkg/enqueue/Consumption/ExtensionInterface.php @@ -2,65 +2,6 @@ namespace Enqueue\Consumption; -interface ExtensionInterface +interface ExtensionInterface extends StartExtensionInterface, PreSubscribeExtensionInterface, PreConsumeExtensionInterface, MessageReceivedExtensionInterface, PostMessageReceivedExtensionInterface, MessageResultExtensionInterface, ProcessorExceptionExtensionInterface, PostConsumeExtensionInterface, EndExtensionInterface { - /** - * Executed only once at the very begining of the consumption. - * At this stage the context does not contain processor, consumer and queue. - * - * @param Context $context - */ - public function onStart(Context $context); - - /** - * Executed at every new cycle before we asked a broker for a new message. - * At this stage the context already contains processor, consumer and queue. - * The consumption could be interrupted at this step. - * - * @param Context $context - */ - public function onBeforeReceive(Context $context); - - /** - * Executed when a new message is received from a broker but before it was passed to processor - * The context contains a message. - * The extension may set a status. If the status is set the exception is thrown - * The consumption could be interrupted at this step but it exits after the message is processed. - * - * @param Context $context - */ - public function onPreReceived(Context $context); - - /** - * Executed when a message is processed by a processor or a result was set in onPreReceived method. - * BUT before the message status was sent to the broker - * The consumption could be interrupted at this step but it exits after the message is processed. - * - * @param Context $context - */ - public function onResult(Context $context); - - /** - * Executed when a message is processed by a processor. - * The context contains a status, which could not be changed. - * The consumption could be interrupted at this step but it exits after the message is processed. - * - * @param Context $context - */ - public function onPostReceived(Context $context); - - /** - * Called each time at the end of the cycle if nothing was done. - * - * @param Context $context - */ - public function onIdle(Context $context); - - /** - * Called when the consumption was interrupted by an extension or exception - * In case of exception it will be present in the context. - * - * @param Context $context - */ - public function onInterrupted(Context $context); } diff --git a/pkg/enqueue/Consumption/MessageReceivedExtensionInterface.php b/pkg/enqueue/Consumption/MessageReceivedExtensionInterface.php new file mode 100644 index 000000000..10afc9cf1 --- /dev/null +++ b/pkg/enqueue/Consumption/MessageReceivedExtensionInterface.php @@ -0,0 +1,15 @@ +interopContext = $interopContext; - $this->staticExtension = $extension ?: new ChainExtension([]); - $this->idleTimeout = $idleTimeout; $this->receiveTimeout = $receiveTimeout; - $this->boundProcessors = []; - $this->logger = new NullLogger(); - $this->fallbackSubscriptionConsumer = new FallbackSubscriptionConsumer(); - } + $this->staticExtension = $extension ?: new ChainExtension([]); + $this->logger = $logger ?: new NullLogger(); - /** - * {@inheritdoc} - */ - public function setIdleTimeout(float $timeout): void - { - $this->idleTimeout = $timeout; - } + $this->boundProcessors = []; + array_walk($boundProcessors, function (BoundProcessor $processor) { + $this->boundProcessors[] = $processor; + }); - /** - * {@inheritdoc} - */ - public function getIdleTimeout(): float - { - return $this->idleTimeout; + $this->fallbackSubscriptionConsumer = new FallbackSubscriptionConsumer(); } - public function setReceiveTimeout(float $timeout): void + public function setReceiveTimeout(int $timeout): void { $this->receiveTimeout = $timeout; } - public function getReceiveTimeout(): float + public function getReceiveTimeout(): int { return $this->receiveTimeout; } @@ -130,51 +116,56 @@ public function bind($queue, Processor $processor): QueueConsumerInterface throw new LogicException(sprintf('The queue was already bound. Queue: %s', $queue->getQueueName())); } - $this->boundProcessors[$queue->getQueueName()] = [$queue, $processor]; + $this->boundProcessors[$queue->getQueueName()] = new BoundProcessor($queue, $processor); return $this; } - /** - * {@inheritdoc} - */ public function bindCallback($queue, callable $processor): QueueConsumerInterface { return $this->bind($queue, new CallbackProcessor($processor)); } - /** - * {@inheritdoc} - */ public function consume(ExtensionInterface $runtimeExtension = null): void { - if (empty($this->boundProcessors)) { - throw new \LogicException('There is nothing to consume. It is required to bind something before calling consume method.'); - } - - /** @var Consumer[] $consumers */ - $consumers = []; - /** @var InteropQueue $queue */ - foreach ($this->boundProcessors as list($queue, $processor)) { - $consumers[$queue->getQueueName()] = $this->interopContext->createConsumer($queue); - } - $this->extension = $runtimeExtension ? new ChainExtension([$this->staticExtension, $runtimeExtension]) : $this->staticExtension ; - $context = new Context($this->interopContext); - $this->extension->onStart($context); + $startTime = (int) (microtime(true) * 1000); + + $start = new Start( + $this->interopContext, + $this->logger, + $this->boundProcessors, + $this->receiveTimeout, + $startTime + ); + + $this->extension->onStart($start); + + if ($start->isExecutionInterrupted()) { + $this->onEnd($startTime); - if ($context->getLogger()) { - $this->logger = $context->getLogger(); - } else { - $this->logger = new NullLogger(); - $context->setLogger($this->logger); + return; + } + + $this->logger = $start->getLogger(); + $this->receiveTimeout = $start->getReceiveTimeout(); + $this->boundProcessors = $start->getBoundProcessors(); + + if (empty($this->boundProcessors)) { + throw new \LogicException('There is nothing to consume. It is required to bind something before calling consume method.'); } - $this->logger->info('Start consuming'); + /** @var Consumer[] $consumers */ + $consumers = []; + foreach ($this->boundProcessors as $queueName => $boundProcessor) { + $queue = $boundProcessor->getQueue(); + + $consumers[$queue->getQueueName()] = $this->interopContext->createConsumer($queue); + } try { $subscriptionConsumer = $this->interopContext->createSubscriptionConsumer(); @@ -182,80 +173,105 @@ public function consume(ExtensionInterface $runtimeExtension = null): void $subscriptionConsumer = $this->fallbackSubscriptionConsumer; } - $callback = function (InteropMessage $message, Consumer $consumer) use (&$context) { - $currentProcessor = null; + $receivedMessagesCount = 0; + $interruptExecution = false; - /** @var InteropQueue $queue */ - foreach ($this->boundProcessors as list($queue, $processor)) { - if ($queue->getQueueName() === $consumer->getQueue()->getQueueName()) { - $currentProcessor = $processor; + $callback = function (InteropMessage $message, Consumer $consumer) use (&$receivedMessagesCount, &$interruptExecution) { + ++$receivedMessagesCount; + + $receivedAt = (int) (microtime(true) * 1000); + $queue = $consumer->getQueue(); + if (false == array_key_exists($queue->getQueueName(), $this->boundProcessors)) { + throw new \LogicException(sprintf('The processor for the queue "%s" could not be found.', $queue->getQueueName())); + } + + $processor = $this->boundProcessors[$queue->getQueueName()]->getProcessor(); + + $messageReceived = new MessageReceived($this->interopContext, $consumer, $message, $processor, $receivedAt, $this->logger); + $this->extension->onMessageReceived($messageReceived); + $result = $messageReceived->getResult(); + $processor = $messageReceived->getProcessor(); + if (null === $result) { + try { + $result = $processor->process($message, $this->interopContext); + } catch (\Exception $e) { + $result = $this->onProcessorException($message, $e, $receivedAt); } } - if (false == $currentProcessor) { - throw new \LogicException(sprintf('The processor for the queue "%s" could not be found.', $consumer->getQueue()->getQueueName())); + $messageResult = new MessageResult($this->interopContext, $message, $result, $receivedAt, $this->logger); + $this->extension->onResult($messageResult); + $result = $messageResult->getResult(); + + switch ($result) { + case Result::ACK: + $consumer->acknowledge($message); + break; + case Result::REJECT: + $consumer->reject($message, false); + break; + case Result::REQUEUE: + $consumer->reject($message, true); + break; + case Result::ALREADY_ACKNOWLEDGED: + break; + default: + throw new \LogicException(sprintf('Status is not supported: %s', $result)); } - $context = new Context($this->interopContext); - $context->setLogger($this->logger); - $context->setInteropQueue($consumer->getQueue()); - $context->setConsumer($consumer); - $context->setProcessor($currentProcessor); - $context->setInteropMessage($message); + $postMessageReceived = new PostMessageReceived($this->interopContext, $message, $result, $receivedAt, $this->logger); + $this->extension->onPostMessageReceived($postMessageReceived); - $this->processMessage($consumer, $currentProcessor, $message, $context); + if ($postMessageReceived->isExecutionInterrupted()) { + $interruptExecution = true; - if ($context->isExecutionInterrupted()) { - throw new ConsumptionInterruptedException(); + return false; } return true; }; - foreach ($consumers as $consumer) { + foreach ($consumers as $queueName => $consumer) { /* @var Consumer $consumer */ + $preSubscribe = new PreSubscribe( + $this->interopContext, + $this->boundProcessors[$queueName]->getProcessor(), + $consumer, + $this->logger + ); + + $this->extension->onPreSubscribe($preSubscribe); + $subscriptionConsumer->subscribe($consumer, $callback); } + $cycle = 1; while (true) { - try { - $this->extension->onBeforeReceive($context); + $receivedMessagesCount = 0; + $interruptExecution = false; - if ($context->isExecutionInterrupted()) { - throw new ConsumptionInterruptedException(); - } - - $subscriptionConsumer->consume($this->receiveTimeout); - - $this->idleTimeout && usleep($this->idleTimeout * 1000); - $this->extension->onIdle($context); - - if ($context->isExecutionInterrupted()) { - throw new ConsumptionInterruptedException(); - } - } catch (ConsumptionInterruptedException $e) { - $this->logger->info(sprintf('Consuming interrupted')); + $preConsume = new PreConsume($this->interopContext, $subscriptionConsumer, $this->logger, $cycle, $this->receiveTimeout, $startTime); + $this->extension->onPreConsume($preConsume); - foreach ($consumers as $consumer) { - /* @var Consumer $consumer */ + if ($preConsume->isExecutionInterrupted()) { + $this->onEnd($startTime, $subscriptionConsumer); - $subscriptionConsumer->unsubscribe($consumer); - } - - $context->setExecutionInterrupted(true); + return; + } - $this->extension->onInterrupted($context); + $subscriptionConsumer->consume($this->receiveTimeout); - return; - } catch (\Throwable $exception) { - $context->setExecutionInterrupted(true); - $context->setException($exception); + $postConsume = new PostConsume($this->interopContext, $subscriptionConsumer, $receivedMessagesCount, $cycle, $startTime, $this->logger); + $this->extension->onPostConsume($postConsume); - $this->onInterruptionByException($this->extension, $context); + if ($interruptExecution || $postConsume->isExecutionInterrupted()) { + $this->onEnd($startTime, $subscriptionConsumer); return; } + + ++$cycle; } } @@ -269,31 +285,36 @@ public function setFallbackSubscriptionConsumer(SubscriptionConsumer $fallbackSu $this->fallbackSubscriptionConsumer = $fallbackSubscriptionConsumer; } + private function onEnd(int $startTime, SubscriptionConsumer $subscriptionConsumer = null): void + { + $endTime = (int) (microtime(true) * 1000); + + $this->extension->onEnd(new End($this->interopContext, $startTime, $endTime, $this->logger)); + + if ($subscriptionConsumer) { + $subscriptionConsumer->unsubscribeAll(); + } + } + /** - * @param ExtensionInterface $extension - * @param Context $context + * The logic is similar to one in Symfony's ExceptionListener::. * - * @throws \Exception + * https://github.com/symfony/symfony/blob/cbe289517470eeea27162fd2d523eb29c95f775f/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php#L77 */ - private function onInterruptionByException(ExtensionInterface $extension, Context $context) + private function onProcessorException(Message $message, \Exception $exception, int $receivedAt) { - $this->logger = $context->getLogger(); - $this->logger->error(sprintf('Consuming interrupted by exception')); - - $exception = $context->getException(); + $processorException = new ProcessorException($this->interopContext, $message, $exception, $receivedAt, $this->logger); try { - $this->extension->onInterrupted($context); - } catch (\Exception $e) { - // logic is similar to one in Symfony's ExceptionListener::onKernelException - $this->logger->error(sprintf( - 'Exception thrown when handling an exception (%s: %s at %s line %s)', - get_class($e), - $e->getMessage(), - $e->getFile(), - $e->getLine() - )); + $this->extension->onProcessorException($processorException); + + $result = $processorException->getResult(); + if (null === $result) { + throw $exception; + } + return $result; + } catch (\Exception $e) { $wrapper = $e; while ($prev = $wrapper->getPrevious()) { if ($exception === $wrapper = $prev) { @@ -310,38 +331,4 @@ private function onInterruptionByException(ExtensionInterface $extension, Contex throw $exception; } - - private function processMessage(Consumer $consumer, Processor $processor, InteropMessage $message, Context $context) - { - $this->logger->info('Message received from the queue: '.$context->getInteropQueue()->getQueueName()); - $this->logger->debug('Headers: {headers}', ['headers' => new VarExport($message->getHeaders())]); - $this->logger->debug('Properties: {properties}', ['properties' => new VarExport($message->getProperties())]); - $this->logger->debug('Payload: {payload}', ['payload' => new VarExport($message->getBody())]); - - $this->extension->onPreReceived($context); - if (!$context->getResult()) { - $result = $processor->process($message, $context->getInteropContext()); - $context->setResult($result); - } - - $this->extension->onResult($context); - - switch ($context->getResult()) { - case Result::ACK: - $consumer->acknowledge($message); - break; - case Result::REJECT: - $consumer->reject($message, false); - break; - case Result::REQUEUE: - $consumer->reject($message, true); - break; - default: - throw new \LogicException(sprintf('Status is not supported: %s', $context->getResult())); - } - - $this->logger->info(sprintf('Message processed: %s', $context->getResult())); - - $this->extension->onPostReceived($context); - } } diff --git a/pkg/enqueue/Consumption/QueueConsumerInterface.php b/pkg/enqueue/Consumption/QueueConsumerInterface.php index 8358ba380..ed229381b 100644 --- a/pkg/enqueue/Consumption/QueueConsumerInterface.php +++ b/pkg/enqueue/Consumption/QueueConsumerInterface.php @@ -9,18 +9,14 @@ interface QueueConsumerInterface { /** - * Milliseconds. + * In milliseconds. */ - public function setIdleTimeout(float $timeout): void; - - public function getIdleTimeout(): float; + public function setReceiveTimeout(int $timeout): void; /** - * Milliseconds. + * In milliseconds. */ - public function setReceiveTimeout(float $timeout): void; - - public function getReceiveTimeout(): float; + public function getReceiveTimeout(): int; public function getContext(): Context; diff --git a/pkg/enqueue/Consumption/Result.php b/pkg/enqueue/Consumption/Result.php index 926f2567d..b94b7447c 100644 --- a/pkg/enqueue/Consumption/Result.php +++ b/pkg/enqueue/Consumption/Result.php @@ -22,6 +22,8 @@ class Result */ const REQUEUE = Processor::REQUEUE; + const ALREADY_ACKNOWLEDGED = 'enqueue.already_acknowledged'; + /** * @var string */ diff --git a/pkg/enqueue/Consumption/StartExtensionInterface.php b/pkg/enqueue/Consumption/StartExtensionInterface.php new file mode 100644 index 000000000..98571061c --- /dev/null +++ b/pkg/enqueue/Consumption/StartExtensionInterface.php @@ -0,0 +1,13 @@ +container->get(sprintf($this->driverIdPatter, $client)); } } + +function enqueue() +{ +} diff --git a/pkg/enqueue/Symfony/Consumption/QueueConsumerOptionsCommandTrait.php b/pkg/enqueue/Symfony/Consumption/QueueConsumerOptionsCommandTrait.php index c20e129b1..9df852df9 100644 --- a/pkg/enqueue/Symfony/Consumption/QueueConsumerOptionsCommandTrait.php +++ b/pkg/enqueue/Symfony/Consumption/QueueConsumerOptionsCommandTrait.php @@ -14,7 +14,6 @@ trait QueueConsumerOptionsCommandTrait protected function configureQueueConsumerOptions() { $this - ->addOption('idle-time', null, InputOption::VALUE_REQUIRED, 'The time in milliseconds queue consumer idle if no message has been received.') ->addOption('receive-timeout', null, InputOption::VALUE_REQUIRED, 'The time in milliseconds queue consumer waits for a message.') ; } @@ -25,12 +24,8 @@ protected function configureQueueConsumerOptions() */ protected function setQueueConsumerOptions(QueueConsumerInterface $consumer, InputInterface $input) { - if (null !== $idleTimeout = $input->getOption('idle-time')) { - $consumer->setIdleTimeout((float) $idleTimeout); - } - if (null !== $receiveTimeout = $input->getOption('receive-timeout')) { - $consumer->setReceiveTimeout((float) $receiveTimeout); + $consumer->setReceiveTimeout((int) $receiveTimeout); } } } diff --git a/pkg/enqueue/Symfony/DependencyInjection/TransportFactory.php b/pkg/enqueue/Symfony/DependencyInjection/TransportFactory.php index 12cc5faa2..b60420c52 100644 --- a/pkg/enqueue/Symfony/DependencyInjection/TransportFactory.php +++ b/pkg/enqueue/Symfony/DependencyInjection/TransportFactory.php @@ -98,11 +98,6 @@ public function addQueueConsumerConfiguration(ArrayNodeDefinition $builder): voi { $builder ->addDefaultsIfNotSet()->children() - ->integerNode('idle_time') - ->min(0) - ->defaultValue(0) - ->info('the time in milliseconds queue consumer waits if no message received') - ->end() ->integerNode('receive_timeout') ->min(0) ->defaultValue(10000) @@ -169,7 +164,6 @@ public function buildQueueConsumer(ContainerBuilder $container, array $config): $contextId = $this->format('context'); $this->assertServiceExists($container, $contextId); - $container->setParameter($this->format('idle_time'), $config['idle_time'] ?? 0); $container->setParameter($this->format('receive_timeout'), $config['receive_timeout'] ?? 10000); $container->register($this->format('consumption_extensions'), ChainExtension::class) @@ -179,7 +173,8 @@ public function buildQueueConsumer(ContainerBuilder $container, array $config): $container->register($this->format('queue_consumer'), QueueConsumer::class) ->addArgument(new Reference($contextId)) ->addArgument(new Reference($this->format('consumption_extensions'))) - ->addArgument($this->format('idle_time', true)) + ->addArgument([]) + ->addArgument(null) ->addArgument($this->format('receive_timeout', true)) ; diff --git a/pkg/enqueue/Tests/Client/ConsumptionExtension/DelayRedeliveredMessageExtensionTest.php b/pkg/enqueue/Tests/Client/ConsumptionExtension/DelayRedeliveredMessageExtensionTest.php index 5d4b7503d..8b6019ec3 100644 --- a/pkg/enqueue/Tests/Client/ConsumptionExtension/DelayRedeliveredMessageExtensionTest.php +++ b/pkg/enqueue/Tests/Client/ConsumptionExtension/DelayRedeliveredMessageExtensionTest.php @@ -5,13 +5,16 @@ use Enqueue\Client\ConsumptionExtension\DelayRedeliveredMessageExtension; use Enqueue\Client\DriverInterface; use Enqueue\Client\Message; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\MessageReceived; use Enqueue\Consumption\Result; use Enqueue\Null\NullMessage; use Enqueue\Null\NullQueue; +use Interop\Queue\Consumer; use Interop\Queue\Context as InteropContext; +use Interop\Queue\Processor; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; class DelayRedeliveredMessageExtensionTest extends TestCase { @@ -61,17 +64,21 @@ public function testShouldSendDelayedMessageAndRejectOriginalMessage() ) ; - $context = new Context($this->createContextMock()); - $context->setInteropQueue($queue); - $context->setInteropMessage($originMessage); - $context->setLogger($logger); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub($queue), + $originMessage, + $this->createProcessorMock(), + 1, + $logger + ); - $this->assertNull($context->getResult()); + $this->assertNull($messageReceived->getResult()); $extension = new DelayRedeliveredMessageExtension($driver, 12345); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); - $result = $context->getResult(); + $result = $messageReceived->getResult(); $this->assertInstanceOf(Result::class, $result); $this->assertSame(Result::REJECT, $result->getStatus()); $this->assertSame('A new copy of the message was sent with a delay. The original message is rejected', $result->getReason()); @@ -92,13 +99,19 @@ public function testShouldDoNothingIfMessageIsNotRedelivered() ->method('sendToProcessor') ; - $context = new Context($this->createContextMock()); - $context->setInteropMessage($message); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub(null), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); $extension = new DelayRedeliveredMessageExtension($driver, 12345); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); - $this->assertNull($context->getResult()); + $this->assertNull($messageReceived->getResult()); } public function testShouldDoNothingIfMessageIsRedeliveredButResultWasAlreadySetOnContext() @@ -112,24 +125,30 @@ public function testShouldDoNothingIfMessageIsRedeliveredButResultWasAlreadySetO ->method('sendToProcessor') ; - $context = new Context($this->createContextMock()); - $context->setInteropMessage($message); - $context->setResult('aStatus'); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub(null), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); + $messageReceived->setResult(Result::ack()); $extension = new DelayRedeliveredMessageExtension($driver, 12345); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); } /** - * @return \PHPUnit_Framework_MockObject_MockObject|DriverInterface + * @return \PHPUnit_Framework_MockObject_MockObject */ - private function createDriverMock() + private function createDriverMock(): DriverInterface { return $this->createMock(DriverInterface::class); } /** - * @return \PHPUnit_Framework_MockObject_MockObject|InteropContext + * @return \PHPUnit_Framework_MockObject_MockObject */ private function createContextMock(): InteropContext { @@ -137,9 +156,34 @@ private function createContextMock(): InteropContext } /** - * @return \PHPUnit_Framework_MockObject_MockObject|LoggerInterface + * @return \PHPUnit_Framework_MockObject_MockObject */ - private function createLoggerMock() + private function createProcessorMock(): Processor + { + return $this->createMock(Processor::class); + } + + /** + * @param mixed $queue + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createConsumerStub($queue): Consumer + { + $consumerMock = $this->createMock(Consumer::class); + $consumerMock + ->expects($this->any()) + ->method('getQueue') + ->willReturn($queue) + ; + + return $consumerMock; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createLoggerMock(): LoggerInterface { return $this->createMock(LoggerInterface::class); } diff --git a/pkg/enqueue/Tests/Client/ConsumptionExtension/ExclusiveCommandExtensionTest.php b/pkg/enqueue/Tests/Client/ConsumptionExtension/ExclusiveCommandExtensionTest.php index 8117645b8..3e1ef2ba0 100644 --- a/pkg/enqueue/Tests/Client/ConsumptionExtension/ExclusiveCommandExtensionTest.php +++ b/pkg/enqueue/Tests/Client/ConsumptionExtension/ExclusiveCommandExtensionTest.php @@ -7,12 +7,14 @@ use Enqueue\Client\DriverInterface; use Enqueue\Client\Route; use Enqueue\Client\RouteCollection; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\ExtensionInterface as ConsumptionExtensionInterface; -use Enqueue\Null\NullContext; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\MessageReceivedExtensionInterface; use Enqueue\Null\NullMessage; use Enqueue\Null\NullQueue; use Enqueue\Test\ClassExtensionTrait; +use Interop\Queue\Consumer; +use Interop\Queue\Context as InteropContext; +use Interop\Queue\Processor; use PHPUnit\Framework\TestCase; use Psr\Log\NullLogger; @@ -20,9 +22,9 @@ class ExclusiveCommandExtensionTest extends TestCase { use ClassExtensionTrait; - public function testShouldImplementConsumptionExtensionInterface() + public function testShouldImplementMessageReceivedExtensionInterface() { - $this->assertClassImplements(ConsumptionExtensionInterface::class, ExclusiveCommandExtension::class); + $this->assertClassImplements(MessageReceivedExtensionInterface::class, ExclusiveCommandExtension::class); } public function testShouldBeFinal() @@ -40,23 +42,29 @@ public function testShouldDoNothingIfMessageHasTopicPropertySetOnPreReceive() $message = new NullMessage(); $message->setProperty(Config::TOPIC, 'aTopic'); - $context = new Context(new NullContext()); - $context->setInteropMessage($message); - $driver = $this->createDriverStub(); $driver ->expects($this->never()) ->method('createQueue') ; + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub(null), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); + $extension = new ExclusiveCommandExtension($driver); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); - self::assertNull($context->getResult()); + self::assertNull($messageReceived->getResult()); $this->assertEquals([ - 'enqueue.topic' => 'aTopic', + Config::TOPIC => 'aTopic', ], $message->getProperties()); } @@ -65,8 +73,14 @@ public function testShouldDoNothingIfMessageHasCommandPropertySetOnPreReceive() $message = new NullMessage(); $message->setProperty(Config::COMMAND, 'aCommand'); - $context = new Context(new NullContext()); - $context->setInteropMessage($message); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub(null), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); $driver = $this->createDriverStub(); $driver @@ -76,12 +90,12 @@ public function testShouldDoNothingIfMessageHasCommandPropertySetOnPreReceive() $extension = new ExclusiveCommandExtension($driver); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); - self::assertNull($context->getResult()); + self::assertNull($messageReceived->getResult()); $this->assertEquals([ - 'enqueue.command' => 'aCommand', + Config::COMMAND => 'aCommand', ], $message->getProperties()); } @@ -90,8 +104,14 @@ public function testShouldDoNothingIfMessageHasProcessorPropertySetOnPreReceive( $message = new NullMessage(); $message->setProperty(Config::PROCESSOR, 'aProcessor'); - $context = new Context(new NullContext()); - $context->setInteropMessage($message); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub(null), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); $driver = $this->createDriverStub(); $driver @@ -101,12 +121,12 @@ public function testShouldDoNothingIfMessageHasProcessorPropertySetOnPreReceive( $extension = new ExclusiveCommandExtension($driver); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); - self::assertNull($context->getResult()); + self::assertNull($messageReceived->getResult()); $this->assertEquals([ - 'enqueue.processor' => 'aProcessor', + Config::PROCESSOR => 'aProcessor', ], $message->getProperties()); } @@ -115,15 +135,20 @@ public function testShouldDoNothingIfCurrentQueueHasNoExclusiveProcessor() $message = new NullMessage(); $queue = new NullQueue('aBarQueueName'); - $context = new Context(new NullContext()); - $context->setInteropMessage($message); - $context->setInteropQueue($queue); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub($queue), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); $extension = new ExclusiveCommandExtension($this->createDriverStub(new RouteCollection([]))); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); - self::assertNull($context->getResult()); + self::assertNull($messageReceived->getResult()); $this->assertEquals([], $message->getProperties()); } @@ -133,10 +158,14 @@ public function testShouldSetCommandPropertiesIfCurrentQueueHasExclusiveCommandP $message = new NullMessage(); $queue = new NullQueue('fooQueue'); - $context = new Context(new NullContext()); - $context->setInteropMessage($message); - $context->setInteropQueue($queue); - $context->setLogger(new NullLogger()); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub($queue), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); $routeCollection = new RouteCollection([ new Route('fooCommand', Route::COMMAND, 'theFooProcessor', [ @@ -159,13 +188,13 @@ public function testShouldSetCommandPropertiesIfCurrentQueueHasExclusiveCommandP ; $extension = new ExclusiveCommandExtension($driver); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); - self::assertNull($context->getResult()); + self::assertNull($messageReceived->getResult()); $this->assertEquals([ - 'enqueue.processor' => 'theFooProcessor', - 'enqueue.command' => 'fooCommand', + Config::PROCESSOR => 'theFooProcessor', + Config::COMMAND => 'fooCommand', ], $message->getProperties()); } @@ -174,10 +203,14 @@ public function testShouldDoNothingIfAnotherQueue() $message = new NullMessage(); $queue = new NullQueue('barQueue'); - $context = new Context(new NullContext()); - $context->setInteropMessage($message); - $context->setInteropQueue($queue); - $context->setLogger(new NullLogger()); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub($queue), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); $routeCollection = new RouteCollection([ new Route('fooCommand', Route::COMMAND, 'theFooProcessor', [ @@ -200,9 +233,9 @@ public function testShouldDoNothingIfAnotherQueue() ; $extension = new ExclusiveCommandExtension($driver); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); - self::assertNull($context->getResult()); + self::assertNull($messageReceived->getResult()); $this->assertEquals([], $message->getProperties()); } @@ -221,4 +254,37 @@ private function createDriverStub(RouteCollection $routeCollection = null): Driv return $driver; } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createContextMock(): InteropContext + { + return $this->createMock(InteropContext::class); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createProcessorMock(): Processor + { + return $this->createMock(Processor::class); + } + + /** + * @param mixed $queue + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createConsumerStub($queue): Consumer + { + $consumerMock = $this->createMock(Consumer::class); + $consumerMock + ->expects($this->any()) + ->method('getQueue') + ->willReturn($queue) + ; + + return $consumerMock; + } } diff --git a/pkg/enqueue/Tests/Client/ConsumptionExtension/FlushSpoolProducerExtensionTest.php b/pkg/enqueue/Tests/Client/ConsumptionExtension/FlushSpoolProducerExtensionTest.php index 1469c99bb..4f3af656e 100644 --- a/pkg/enqueue/Tests/Client/ConsumptionExtension/FlushSpoolProducerExtensionTest.php +++ b/pkg/enqueue/Tests/Client/ConsumptionExtension/FlushSpoolProducerExtensionTest.php @@ -4,86 +4,36 @@ use Enqueue\Client\ConsumptionExtension\FlushSpoolProducerExtension; use Enqueue\Client\SpoolProducer; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\End; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\EndExtensionInterface; +use Enqueue\Consumption\PostMessageReceivedExtensionInterface; use Enqueue\Test\ClassExtensionTrait; +use Interop\Queue\Context; +use Interop\Queue\Message; use PHPUnit\Framework\TestCase; +use Psr\Log\NullLogger; class FlushSpoolProducerExtensionTest extends TestCase { use ClassExtensionTrait; - public function testShouldImplementExtensionInterface() + public function testShouldImplementPostMessageReceivedExtensionInterface() { - $this->assertClassImplements(ExtensionInterface::class, FlushSpoolProducerExtension::class); + $this->assertClassImplements(PostMessageReceivedExtensionInterface::class, FlushSpoolProducerExtension::class); } - public function testCouldBeConstructedWithSpoolProducerAsFirstArgument() - { - new FlushSpoolProducerExtension($this->createSpoolProducerMock()); - } - - public function testShouldDoNothingOnStart() - { - $producer = $this->createSpoolProducerMock(); - $producer - ->expects(self::never()) - ->method('flush') - ; - - $extension = new FlushSpoolProducerExtension($producer); - $extension->onStart($this->createContextMock()); - } - - public function testShouldDoNothingOnBeforeReceive() - { - $producer = $this->createSpoolProducerMock(); - $producer - ->expects(self::never()) - ->method('flush') - ; - - $extension = new FlushSpoolProducerExtension($producer); - $extension->onBeforeReceive($this->createContextMock()); - } - - public function testShouldDoNothingOnPreReceived() - { - $producer = $this->createSpoolProducerMock(); - $producer - ->expects(self::never()) - ->method('flush') - ; - - $extension = new FlushSpoolProducerExtension($producer); - $extension->onPreReceived($this->createContextMock()); - } - - public function testShouldDoNothingOnResult() + public function testShouldImplementEndExtensionInterface() { - $producer = $this->createSpoolProducerMock(); - $producer - ->expects(self::never()) - ->method('flush') - ; - - $extension = new FlushSpoolProducerExtension($producer); - $extension->onResult($this->createContextMock()); + $this->assertClassImplements(EndExtensionInterface::class, FlushSpoolProducerExtension::class); } - public function testShouldDoNothingOnIdle() + public function testCouldBeConstructedWithSpoolProducerAsFirstArgument() { - $producer = $this->createSpoolProducerMock(); - $producer - ->expects(self::never()) - ->method('flush') - ; - - $extension = new FlushSpoolProducerExtension($producer); - $extension->onIdle($this->createContextMock()); + new FlushSpoolProducerExtension($this->createSpoolProducerMock()); } - public function testShouldFlushSpoolProducerOnInterrupted() + public function testShouldFlushSpoolProducerOnEnd() { $producer = $this->createSpoolProducerMock(); $producer @@ -91,8 +41,10 @@ public function testShouldFlushSpoolProducerOnInterrupted() ->method('flush') ; + $end = new End($this->createInteropContextMock(), 1, 2, new NullLogger()); + $extension = new FlushSpoolProducerExtension($producer); - $extension->onInterrupted($this->createContextMock()); + $extension->onEnd($end); } public function testShouldFlushSpoolProducerOnPostReceived() @@ -103,14 +55,22 @@ public function testShouldFlushSpoolProducerOnPostReceived() ->method('flush') ; + $context = new PostMessageReceived( + $this->createInteropContextMock(), + $this->createMock(Message::class), + 'aResult', + 1, + new NullLogger() + ); + $extension = new FlushSpoolProducerExtension($producer); - $extension->onPostReceived($this->createContextMock()); + $extension->onPostMessageReceived($context); } /** - * @return \PHPUnit_Framework_MockObject_MockObject|Context + * @return \PHPUnit_Framework_MockObject_MockObject */ - private function createContextMock() + private function createInteropContextMock(): Context { return $this->createMock(Context::class); } diff --git a/pkg/enqueue/Tests/Client/ConsumptionExtension/SetRouterPropertiesExtensionTest.php b/pkg/enqueue/Tests/Client/ConsumptionExtension/SetRouterPropertiesExtensionTest.php index 2d21b904f..be5609db6 100644 --- a/pkg/enqueue/Tests/Client/ConsumptionExtension/SetRouterPropertiesExtensionTest.php +++ b/pkg/enqueue/Tests/Client/ConsumptionExtension/SetRouterPropertiesExtensionTest.php @@ -5,12 +5,14 @@ use Enqueue\Client\Config; use Enqueue\Client\ConsumptionExtension\SetRouterPropertiesExtension; use Enqueue\Client\DriverInterface; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\MessageReceivedExtensionInterface; use Enqueue\Null\NullMessage; use Enqueue\Null\NullQueue; use Enqueue\Test\ClassExtensionTrait; +use Interop\Queue\Consumer; use Interop\Queue\Context as InteropContext; +use Interop\Queue\Processor; use PHPUnit\Framework\TestCase; use Psr\Log\NullLogger; @@ -18,9 +20,9 @@ class SetRouterPropertiesExtensionTest extends TestCase { use ClassExtensionTrait; - public function testShouldImplementExtensionInterface() + public function testShouldImplementMessageReceivedExtensionInterface() { - $this->assertClassImplements(ExtensionInterface::class, SetRouterPropertiesExtension::class); + $this->assertClassImplements(MessageReceivedExtensionInterface::class, SetRouterPropertiesExtension::class); } public function testCouldBeConstructedWithRequiredArguments() @@ -48,16 +50,20 @@ public function testShouldSetRouterProcessorPropertyIfNotSetAndOnRouterQueue() $message = new NullMessage(); - $context = new Context($this->createContextMock()); - $context->setLogger(new NullLogger()); - $context->setInteropMessage($message); - $context->setInteropQueue(new NullQueue('test.router-queue')); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub(new NullQueue('test.router-queue')), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); $extension = new SetRouterPropertiesExtension($driver); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); $this->assertEquals([ - 'enqueue.processor' => 'router-processor-name', + Config::PROCESSOR => 'router-processor-name', ], $message->getProperties()); } @@ -81,12 +87,17 @@ public function testShouldNotSetRouterProcessorPropertyIfNotSetAndNotOnRouterQue $message = new NullMessage(); - $context = new Context($this->createContextMock()); - $context->setInteropMessage($message); - $context->setInteropQueue(new NullQueue('test.another-queue')); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub(new NullQueue('test.another-queue')), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); $extension = new SetRouterPropertiesExtension($driver); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); $this->assertEquals([], $message->getProperties()); } @@ -102,11 +113,17 @@ public function testShouldNotSetAnyPropertyIfProcessorNamePropertyAlreadySet() $message = new NullMessage(); $message->setProperty(Config::PROCESSOR, 'non-router-processor'); - $context = new Context($this->createContextMock()); - $context->setInteropMessage($message); + $messageReceived = new MessageReceived( + $this->createContextMock(), + $this->createConsumerStub(null), + $message, + $this->createProcessorMock(), + 1, + new NullLogger() + ); $extension = new SetRouterPropertiesExtension($driver); - $extension->onPreReceived($context); + $extension->onMessageReceived($messageReceived); $this->assertEquals([ 'enqueue.processor' => 'non-router-processor', @@ -124,8 +141,33 @@ protected function createContextMock(): InteropContext /** * @return \PHPUnit_Framework_MockObject_MockObject|DriverInterface */ - protected function createDriverMock() + protected function createDriverMock(): DriverInterface { return $this->createMock(DriverInterface::class); } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createProcessorMock(): Processor + { + return $this->createMock(Processor::class); + } + + /** + * @param mixed $queue + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createConsumerStub($queue): Consumer + { + $consumerMock = $this->createMock(Consumer::class); + $consumerMock + ->expects($this->any()) + ->method('getQueue') + ->willReturn($queue) + ; + + return $consumerMock; + } } diff --git a/pkg/enqueue/Tests/Client/ConsumptionExtension/SetupBrokerExtensionTest.php b/pkg/enqueue/Tests/Client/ConsumptionExtension/SetupBrokerExtensionTest.php index 1339dd4c2..014c23289 100644 --- a/pkg/enqueue/Tests/Client/ConsumptionExtension/SetupBrokerExtensionTest.php +++ b/pkg/enqueue/Tests/Client/ConsumptionExtension/SetupBrokerExtensionTest.php @@ -4,8 +4,8 @@ use Enqueue\Client\ConsumptionExtension\SetupBrokerExtension; use Enqueue\Client\DriverInterface; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\Context\Start; +use Enqueue\Consumption\StartExtensionInterface; use Enqueue\Test\ClassExtensionTrait; use Interop\Queue\Context as InteropContext; use PHPUnit\Framework\TestCase; @@ -15,9 +15,9 @@ class SetupBrokerExtensionTest extends TestCase { use ClassExtensionTrait; - public function testShouldImplementExtensionInterface() + public function testShouldImplementStartExtensionInterface() { - $this->assertClassImplements(ExtensionInterface::class, SetupBrokerExtension::class); + $this->assertClassImplements(StartExtensionInterface::class, SetupBrokerExtension::class); } public function testCouldBeConstructedWithRequiredArguments() @@ -36,8 +36,7 @@ public function testShouldSetupBroker() ->with($this->identicalTo($logger)) ; - $context = new Context($this->createMock(InteropContext::class)); - $context->setLogger($logger); + $context = new Start($this->createMock(InteropContext::class), $logger, [], 0, 0); $extension = new SetupBrokerExtension($driver); $extension->onStart($context); @@ -54,8 +53,7 @@ public function testShouldSetupBrokerOnlyOnce() ->with($this->identicalTo($logger)) ; - $context = new Context($this->createMock(InteropContext::class)); - $context->setLogger($logger); + $context = new Start($this->createMock(InteropContext::class), $logger, [], 0, 0); $extension = new SetupBrokerExtension($driver); $extension->onStart($context); diff --git a/pkg/enqueue/Tests/Consumption/ChainExtensionTest.php b/pkg/enqueue/Tests/Consumption/ChainExtensionTest.php index 4c412c661..cf905d898 100644 --- a/pkg/enqueue/Tests/Consumption/ChainExtensionTest.php +++ b/pkg/enqueue/Tests/Consumption/ChainExtensionTest.php @@ -3,10 +3,24 @@ namespace Enqueue\Tests\Consumption; use Enqueue\Consumption\ChainExtension; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\End; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\Context\MessageResult; +use Enqueue\Consumption\Context\PostConsume; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\PreConsume; +use Enqueue\Consumption\Context\PreSubscribe; +use Enqueue\Consumption\Context\Start; use Enqueue\Consumption\ExtensionInterface; use Enqueue\Test\ClassExtensionTrait; +use Interop\Queue\Consumer; +use Interop\Queue\Context; +use Interop\Queue\Message; +use Interop\Queue\Processor; +use Interop\Queue\SubscriptionConsumer; use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; class ChainExtensionTest extends TestCase { @@ -24,7 +38,7 @@ public function testCouldBeConstructedWithExtensionsArray() public function testShouldProxyOnStartToAllInternalExtensions() { - $context = $this->createContextMock(); + $context = new Start($this->createInteropContextMock(), $this->createLoggerMock(), [], 0, 0); $fooExtension = $this->createExtension(); $fooExtension @@ -44,53 +58,99 @@ public function testShouldProxyOnStartToAllInternalExtensions() $extensions->onStart($context); } - public function testShouldProxyOnBeforeReceiveToAllInternalExtensions() + public function testShouldProxyOnPreSubscribeToAllInternalExtensions() { - $context = $this->createContextMock(); + $context = new PreSubscribe( + $this->createInteropContextMock(), + $this->createInteropProcessorMock(), + $this->createInteropConsumerMock(), + $this->createLoggerMock() + ); $fooExtension = $this->createExtension(); $fooExtension ->expects($this->once()) - ->method('onBeforeReceive') + ->method('onPreSubscribe') ->with($this->identicalTo($context)) ; $barExtension = $this->createExtension(); $barExtension ->expects($this->once()) - ->method('onBeforeReceive') + ->method('onPreSubscribe') ->with($this->identicalTo($context)) ; $extensions = new ChainExtension([$fooExtension, $barExtension]); - $extensions->onBeforeReceive($context); + $extensions->onPreSubscribe($context); + } + + public function testShouldProxyOnPreConsumeToAllInternalExtensions() + { + $context = new PreConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + new NullLogger(), + 1, + 2, + 3 + ); + + $fooExtension = $this->createExtension(); + $fooExtension + ->expects($this->once()) + ->method('onPreConsume') + ->with($this->identicalTo($context)) + ; + $barExtension = $this->createExtension(); + $barExtension + ->expects($this->once()) + ->method('onPreConsume') + ->with($this->identicalTo($context)) + ; + + $extensions = new ChainExtension([$fooExtension, $barExtension]); + $extensions->onPreConsume($context); } public function testShouldProxyOnPreReceiveToAllInternalExtensions() { - $context = $this->createContextMock(); + $context = new MessageReceived( + $this->createInteropContextMock(), + $this->createMock(Consumer::class), + $this->createMock(Message::class), + $this->createMock(Processor::class), + 1, + new NullLogger() + ); $fooExtension = $this->createExtension(); $fooExtension ->expects($this->once()) - ->method('onPreReceived') + ->method('onMessageReceived') ->with($this->identicalTo($context)) ; $barExtension = $this->createExtension(); $barExtension ->expects($this->once()) - ->method('onPreReceived') + ->method('onMessageReceived') ->with($this->identicalTo($context)) ; $extensions = new ChainExtension([$fooExtension, $barExtension]); - $extensions->onPreReceived($context); + $extensions->onMessageReceived($context); } public function testShouldProxyOnResultToAllInternalExtensions() { - $context = $this->createContextMock(); + $context = new MessageResult( + $this->createInteropContextMock(), + $this->createMock(Message::class), + 'aResult', + 1, + new NullLogger() + ); $fooExtension = $this->createExtension(); $fooExtension @@ -112,78 +172,115 @@ public function testShouldProxyOnResultToAllInternalExtensions() public function testShouldProxyOnPostReceiveToAllInternalExtensions() { - $context = $this->createContextMock(); + $context = new PostMessageReceived( + $this->createInteropContextMock(), + $this->createMock(Message::class), + 'aResult', + 1, + new NullLogger() + ); $fooExtension = $this->createExtension(); $fooExtension ->expects($this->once()) - ->method('onPostReceived') + ->method('onPostMessageReceived') ->with($this->identicalTo($context)) ; $barExtension = $this->createExtension(); $barExtension ->expects($this->once()) - ->method('onPostReceived') + ->method('onPostMessageReceived') ->with($this->identicalTo($context)) ; $extensions = new ChainExtension([$fooExtension, $barExtension]); - $extensions->onPostReceived($context); + $extensions->onPostMessageReceived($context); } - public function testShouldProxyOnIdleToAllInternalExtensions() + public function testShouldProxyOnPostConsumeToAllInternalExtensions() { - $context = $this->createContextMock(); + $postConsume = new PostConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + 1, + 1, + 1, + new NullLogger() + ); $fooExtension = $this->createExtension(); $fooExtension ->expects($this->once()) - ->method('onIdle') - ->with($this->identicalTo($context)) + ->method('onPostConsume') + ->with($this->identicalTo($postConsume)) ; $barExtension = $this->createExtension(); $barExtension ->expects($this->once()) - ->method('onIdle') - ->with($this->identicalTo($context)) + ->method('onPostConsume') + ->with($this->identicalTo($postConsume)) ; $extensions = new ChainExtension([$fooExtension, $barExtension]); - $extensions->onIdle($context); + $extensions->onPostConsume($postConsume); } - public function testShouldProxyOnInterruptedToAllInternalExtensions() + public function testShouldProxyOnEndToAllInternalExtensions() { - $context = $this->createContextMock(); + $context = new End($this->createInteropContextMock(), 1, 2, new NullLogger()); $fooExtension = $this->createExtension(); $fooExtension ->expects($this->once()) - ->method('onInterrupted') + ->method('onEnd') ->with($this->identicalTo($context)) ; $barExtension = $this->createExtension(); $barExtension ->expects($this->once()) - ->method('onInterrupted') + ->method('onEnd') ->with($this->identicalTo($context)) ; $extensions = new ChainExtension([$fooExtension, $barExtension]); - $extensions->onInterrupted($context); + $extensions->onEnd($context); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function createLoggerMock(): LoggerInterface + { + return $this->createMock(LoggerInterface::class); } /** - * @return \PHPUnit_Framework_MockObject_MockObject|Context + * @return \PHPUnit_Framework_MockObject_MockObject */ - protected function createContextMock() + protected function createInteropContextMock(): Context { return $this->createMock(Context::class); } + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function createInteropConsumerMock(): Consumer + { + return $this->createMock(Consumer::class); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function createInteropProcessorMock(): Processor + { + return $this->createMock(Processor::class); + } + /** * @return \PHPUnit_Framework_MockObject_MockObject|ExtensionInterface */ @@ -191,4 +288,12 @@ protected function createExtension() { return $this->createMock(ExtensionInterface::class); } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createSubscriptionConsumerMock(): SubscriptionConsumer + { + return $this->createMock(SubscriptionConsumer::class); + } } diff --git a/pkg/enqueue/Tests/Consumption/ContextTest.php b/pkg/enqueue/Tests/Consumption/ContextTest.php deleted file mode 100644 index f110597ae..000000000 --- a/pkg/enqueue/Tests/Consumption/ContextTest.php +++ /dev/null @@ -1,258 +0,0 @@ -createContext()); - } - - public function testShouldAllowGetSessionSetInConstructor() - { - $interopContext = $this->createContext(); - - $context = new Context($interopContext); - - $this->assertSame($interopContext, $context->getInteropContext()); - } - - public function testShouldAllowGetMessageConsumerPreviouslySet() - { - $messageConsumer = $this->createConsumer(); - - $context = new Context($this->createContext()); - $context->setConsumer($messageConsumer); - - $this->assertSame($messageConsumer, $context->getConsumer()); - } - - public function testThrowOnTryToChangeMessageConsumerIfAlreadySet() - { - $messageConsumer = $this->createConsumer(); - $anotherMessageConsumer = $this->createConsumer(); - - $context = new Context($this->createContext()); - - $context->setConsumer($messageConsumer); - - $this->expectException(IllegalContextModificationException::class); - - $context->setConsumer($anotherMessageConsumer); - } - - public function testShouldAllowGetMessageProducerPreviouslySet() - { - $processorMock = $this->createProcessorMock(); - - $context = new Context($this->createContext()); - $context->setProcessor($processorMock); - - $this->assertSame($processorMock, $context->getProcessor()); - } - - public function testThrowOnTryToChangeProcessorIfAlreadySet() - { - $processor = $this->createProcessorMock(); - $anotherProcessor = $this->createProcessorMock(); - - $context = new Context($this->createContext()); - - $context->setProcessor($processor); - - $this->expectException(IllegalContextModificationException::class); - - $context->setProcessor($anotherProcessor); - } - - public function testShouldAllowGetLoggerPreviouslySet() - { - $logger = new NullLogger(); - - $context = new Context($this->createContext()); - $context->setLogger($logger); - - $this->assertSame($logger, $context->getLogger()); - } - - public function testShouldSetExecutionInterruptedToFalseInConstructor() - { - $context = new Context($this->createContext()); - - $this->assertFalse($context->isExecutionInterrupted()); - } - - public function testShouldAllowGetPreviouslySetMessage() - { - /** @var InteropMessage $message */ - $message = $this->createMock(InteropMessage::class); - - $context = new Context($this->createContext()); - - $context->setInteropMessage($message); - - $this->assertSame($message, $context->getInteropMessage()); - } - - public function testThrowOnTryToChangeMessageIfAlreadySet() - { - /** @var InteropMessage $message */ - $message = $this->createMock(InteropMessage::class); - - $context = new Context($this->createContext()); - - $this->expectException(IllegalContextModificationException::class); - $this->expectExceptionMessage('The message could be set once'); - - $context->setInteropMessage($message); - $context->setInteropMessage($message); - } - - public function testShouldAllowGetPreviouslySetException() - { - $exception = new \Exception(); - - $context = new Context($this->createContext()); - - $context->setException($exception); - - $this->assertSame($exception, $context->getException()); - } - - public function testShouldAllowGetPreviouslySetResult() - { - $result = 'aResult'; - - $context = new Context($this->createContext()); - - $context->setResult($result); - - $this->assertSame($result, $context->getResult()); - } - - public function testThrowOnTryToChangeResultIfAlreadySet() - { - $result = 'aResult'; - - $context = new Context($this->createContext()); - - $this->expectException(IllegalContextModificationException::class); - $this->expectExceptionMessage('The result modification is not allowed'); - - $context->setResult($result); - $context->setResult($result); - } - - public function testShouldAllowGetPreviouslySetExecutionInterrupted() - { - $context = new Context($this->createContext()); - - // guard - $this->assertFalse($context->isExecutionInterrupted()); - - $context->setExecutionInterrupted(true); - - $this->assertTrue($context->isExecutionInterrupted()); - } - - public function testThrowOnTryToRollbackExecutionInterruptedIfAlreadySetToTrue() - { - $context = new Context($this->createContext()); - - $this->expectException(IllegalContextModificationException::class); - $this->expectExceptionMessage('The execution once interrupted could not be roll backed'); - - $context->setExecutionInterrupted(true); - $context->setExecutionInterrupted(false); - } - - public function testNotThrowOnSettingExecutionInterruptedToTrueIfAlreadySetToTrue() - { - $context = new Context($this->createContext()); - - $context->setExecutionInterrupted(true); - $context->setExecutionInterrupted(true); - } - - public function testShouldAllowGetPreviouslySetLogger() - { - $expectedLogger = new NullLogger(); - - $context = new Context($this->createContext()); - - $context->setLogger($expectedLogger); - - $this->assertSame($expectedLogger, $context->getLogger()); - } - - public function testThrowOnSettingLoggerIfAlreadySet() - { - $context = new Context($this->createContext()); - - $context->setLogger(new NullLogger()); - - $this->expectException(IllegalContextModificationException::class); - $this->expectExceptionMessage('The logger modification is not allowed'); - - $context->setLogger(new NullLogger()); - } - - public function testShouldAllowGetPreviouslySetQueue() - { - $context = new Context($this->createContext()); - - $context->setInteropQueue($queue = new NullQueue('')); - - $this->assertSame($queue, $context->getInteropQueue()); - } - - public function testThrowOnSettingQueueNameIfAlreadySet() - { - $context = new Context($this->createContext()); - - $context->setInteropQueue(new NullQueue('')); - - $this->expectException(IllegalContextModificationException::class); - $this->expectExceptionMessage('The queue modification is not allowed'); - - $context->setInteropQueue(new NullQueue('')); - } - - /** - * @return \PHPUnit_Framework_MockObject_MockObject|InteropContext - */ - protected function createContext(): InteropContext - { - return $this->createMock(InteropContext::class); - } - - /** - * @return \PHPUnit_Framework_MockObject_MockObject|Consumer - */ - protected function createConsumer() - { - return $this->createMock(Consumer::class); - } - - /** - * @return \PHPUnit_Framework_MockObject_MockObject|Processor - */ - protected function createProcessorMock() - { - return $this->createMock(Processor::class); - } -} diff --git a/pkg/enqueue/Tests/Consumption/EmptyExtensionTraitTest.php b/pkg/enqueue/Tests/Consumption/EmptyExtensionTraitTest.php deleted file mode 100644 index 32ea8612a..000000000 --- a/pkg/enqueue/Tests/Consumption/EmptyExtensionTraitTest.php +++ /dev/null @@ -1,20 +0,0 @@ -assertClassImplements(ExceptionInterface::class, ConsumptionInterruptedException::class); - } - - public function testShouldExtendLogicException() - { - $this->assertClassExtends(\LogicException::class, ConsumptionInterruptedException::class); - } - - public function testCouldBeConstructedWithoutAnyArguments() - { - new ConsumptionInterruptedException(); - } -} diff --git a/pkg/enqueue/Tests/Consumption/Extension/LimitConsumedMessagesExtensionTest.php b/pkg/enqueue/Tests/Consumption/Extension/LimitConsumedMessagesExtensionTest.php index 4c3d7557f..2f4f8041b 100644 --- a/pkg/enqueue/Tests/Consumption/Extension/LimitConsumedMessagesExtensionTest.php +++ b/pkg/enqueue/Tests/Consumption/Extension/LimitConsumedMessagesExtensionTest.php @@ -2,13 +2,15 @@ namespace Enqueue\Tests\Consumption\Extension; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\PreConsume; use Enqueue\Consumption\Extension\LimitConsumedMessagesExtension; -use Interop\Queue\Consumer; -use Interop\Queue\Context as InteropContext; -use Interop\Queue\Processor; +use Interop\Queue\Context; +use Interop\Queue\Message; +use Interop\Queue\SubscriptionConsumer; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; class LimitConsumedMessagesExtensionTest extends TestCase { @@ -17,26 +19,69 @@ public function testCouldBeConstructedWithRequiredArguments() new LimitConsumedMessagesExtension(12345); } - public function testShouldThrowExceptionIfMessageLimitIsNotInt() + public function testOnPreConsumeShouldInterruptWhenLimitIsReached() { - $this->setExpectedException( - \InvalidArgumentException::class, - 'Expected message limit is int but got: "double"' + $logger = $this->createLoggerMock(); + $logger + ->expects($this->once()) + ->method('debug') + ->with('[LimitConsumedMessagesExtension] Message consumption is interrupted since'. + ' the message limit reached. limit: "3"') + ; + + $context = new PreConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + $logger, + 1, + 2, + 3 ); - new LimitConsumedMessagesExtension(0.0); + // guard + $this->assertFalse($context->isExecutionInterrupted()); + + // test + $extension = new LimitConsumedMessagesExtension(3); + + $extension->onPreConsume($context); + $this->assertFalse($context->isExecutionInterrupted()); + + $postReceivedMessage = new PostMessageReceived( + $this->createInteropContextMock(), + $this->createMock(Message::class), + 'aResult', + 1, + new NullLogger() + ); + + $extension->onPostMessageReceived($postReceivedMessage); + $extension->onPostMessageReceived($postReceivedMessage); + $extension->onPostMessageReceived($postReceivedMessage); + + $extension->onPreConsume($context); + $this->assertTrue($context->isExecutionInterrupted()); } - public function testOnBeforeReceiveShouldInterruptExecutionIfLimitIsZero() + public function testOnPreConsumeShouldInterruptExecutionIfLimitIsZero() { - $context = $this->createContext(); - $context->getLogger() + $logger = $this->createLoggerMock(); + $logger ->expects($this->once()) ->method('debug') ->with('[LimitConsumedMessagesExtension] Message consumption is interrupted since'. ' the message limit reached. limit: "0"') ; + $context = new PreConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + $logger, + 1, + 2, + 3 + ); + // guard $this->assertFalse($context->isExecutionInterrupted()); @@ -44,20 +89,29 @@ public function testOnBeforeReceiveShouldInterruptExecutionIfLimitIsZero() $extension = new LimitConsumedMessagesExtension(0); // consume 1 - $extension->onBeforeReceive($context); + $extension->onPreConsume($context); $this->assertTrue($context->isExecutionInterrupted()); } - public function testOnBeforeReceiveShouldInterruptExecutionIfLimitIsLessThatZero() + public function testOnPreConsumeShouldInterruptExecutionIfLimitIsLessThatZero() { - $context = $this->createContext(); - $context->getLogger() + $logger = $this->createLoggerMock(); + $logger ->expects($this->once()) ->method('debug') ->with('[LimitConsumedMessagesExtension] Message consumption is interrupted since'. ' the message limit reached. limit: "-1"') ; + $context = new PreConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + $logger, + 1, + 2, + 3 + ); + // guard $this->assertFalse($context->isExecutionInterrupted()); @@ -65,45 +119,64 @@ public function testOnBeforeReceiveShouldInterruptExecutionIfLimitIsLessThatZero $extension = new LimitConsumedMessagesExtension(-1); // consume 1 - $extension->onBeforeReceive($context); + $extension->onPreConsume($context); $this->assertTrue($context->isExecutionInterrupted()); } public function testOnPostReceivedShouldInterruptExecutionIfMessageLimitExceeded() { - $context = $this->createContext(); - $context->getLogger() + $logger = $this->createLoggerMock(); + $logger ->expects($this->once()) ->method('debug') ->with('[LimitConsumedMessagesExtension] Message consumption is interrupted since'. ' the message limit reached. limit: "2"') ; + $postReceivedMessage = new PostMessageReceived( + $this->createInteropContextMock(), + $this->createMock(Message::class), + 'aResult', + 1, + $logger + ); + // guard - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postReceivedMessage->isExecutionInterrupted()); // test $extension = new LimitConsumedMessagesExtension(2); // consume 1 - $extension->onPostReceived($context); - $this->assertFalse($context->isExecutionInterrupted()); + $extension->onPostMessageReceived($postReceivedMessage); + $this->assertFalse($postReceivedMessage->isExecutionInterrupted()); // consume 2 and exit - $extension->onPostReceived($context); - $this->assertTrue($context->isExecutionInterrupted()); + $extension->onPostMessageReceived($postReceivedMessage); + $this->assertTrue($postReceivedMessage->isExecutionInterrupted()); } /** - * @return Context + * @return \PHPUnit_Framework_MockObject_MockObject */ - protected function createContext(): Context + protected function createInteropContextMock(): Context { - $context = new Context($this->createMock(InteropContext::class)); - $context->setLogger($this->createMock(LoggerInterface::class)); - $context->setConsumer($this->createMock(Consumer::class)); - $context->setProcessor($this->createMock(Processor::class)); + return $this->createMock(Context::class); + } - return $context; + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createSubscriptionConsumerMock(): SubscriptionConsumer + { + return $this->createMock(SubscriptionConsumer::class); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createLoggerMock(): LoggerInterface + { + return $this->createMock(LoggerInterface::class); } } diff --git a/pkg/enqueue/Tests/Consumption/Extension/LimitConsumerMemoryExtensionTest.php b/pkg/enqueue/Tests/Consumption/Extension/LimitConsumerMemoryExtensionTest.php index e42e55972..8af630c51 100644 --- a/pkg/enqueue/Tests/Consumption/Extension/LimitConsumerMemoryExtensionTest.php +++ b/pkg/enqueue/Tests/Consumption/Extension/LimitConsumerMemoryExtensionTest.php @@ -2,13 +2,16 @@ namespace Enqueue\Tests\Consumption\Extension; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\PostConsume; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\PreConsume; use Enqueue\Consumption\Extension\LimitConsumerMemoryExtension; -use Interop\Queue\Consumer; -use Interop\Queue\Context as InteropContext; -use Interop\Queue\Processor; +use Interop\Queue\Context; +use Interop\Queue\Message; +use Interop\Queue\SubscriptionConsumer; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; class LimitConsumerMemoryExtensionTest extends TestCase { @@ -24,115 +27,172 @@ public function testShouldThrowExceptionIfMemoryLimitIsNotInt() new LimitConsumerMemoryExtension(0.0); } - public function testOnIdleShouldInterruptExecutionIfMemoryLimitReached() + public function testOnPostConsumeShouldInterruptExecutionIfMemoryLimitReached() { - $context = $this->createContext(); - $context->getLogger() + $logger = $this->createLoggerMock(); + $logger ->expects($this->once()) ->method('debug') ->with($this->stringContains('[LimitConsumerMemoryExtension] Interrupt execution as memory limit reached.')) ; + $postConsume = new PostConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + 1, + 1, + 1, + $logger + ); + // guard - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postConsume->isExecutionInterrupted()); // test $extension = new LimitConsumerMemoryExtension(1); - $extension->onIdle($context); + $extension->onPostConsume($postConsume); - $this->assertTrue($context->isExecutionInterrupted()); + $this->assertTrue($postConsume->isExecutionInterrupted()); } public function testOnPostReceivedShouldInterruptExecutionIfMemoryLimitReached() { - $context = $this->createContext(); - $context->getLogger() + $logger = $this->createLoggerMock(); + $logger ->expects($this->once()) ->method('debug') ->with($this->stringContains('[LimitConsumerMemoryExtension] Interrupt execution as memory limit reached.')) ; + $postReceivedMessage = new PostMessageReceived( + $this->createInteropContextMock(), + $this->createMock(Message::class), + 'aResult', + 1, + $logger + ); + // guard - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postReceivedMessage->isExecutionInterrupted()); // test $extension = new LimitConsumerMemoryExtension(1); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); - $this->assertTrue($context->isExecutionInterrupted()); + $this->assertTrue($postReceivedMessage->isExecutionInterrupted()); } - public function testOnBeforeReceivedShouldInterruptExecutionIfMemoryLimitReached() + public function testOnPreConsumeShouldInterruptExecutionIfMemoryLimitReached() { - $context = $this->createContext(); - $context->getLogger() + $logger = $this->createLoggerMock(); + $logger ->expects($this->once()) ->method('debug') ->with($this->stringContains('[LimitConsumerMemoryExtension] Interrupt execution as memory limit reached.')) ; + $context = new PreConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + $logger, + 1, + 2, + 3 + ); + // guard $this->assertFalse($context->isExecutionInterrupted()); // test $extension = new LimitConsumerMemoryExtension(1); - $extension->onBeforeReceive($context); + $extension->onPreConsume($context); $this->assertTrue($context->isExecutionInterrupted()); } - public function testOnBeforeReceiveShouldNotInterruptExecutionIfMemoryLimitIsNotReached() + public function testOnPreConsumeShouldNotInterruptExecutionIfMemoryLimitIsNotReached() { - $context = $this->createContext(); + $context = new PreConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + new NullLogger(), + 1, + 2, + 3 + ); // guard $this->assertFalse($context->isExecutionInterrupted()); // test $extension = new LimitConsumerMemoryExtension(PHP_INT_MAX); - $extension->onBeforeReceive($context); + $extension->onPreConsume($context); $this->assertFalse($context->isExecutionInterrupted()); } - public function testOnIdleShouldNotInterruptExecutionIfMemoryLimitIsNotReached() + public function testOnPostConsumeShouldNotInterruptExecutionIfMemoryLimitIsNotReached() { - $context = $this->createContext(); + $postConsume = new PostConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + 1, + 1, + 1, + new NullLogger() + ); // guard - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postConsume->isExecutionInterrupted()); // test $extension = new LimitConsumerMemoryExtension(PHP_INT_MAX); - $extension->onIdle($context); + $extension->onPostConsume($postConsume); - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postConsume->isExecutionInterrupted()); } - public function testOnPostReceivedShouldNotInterruptExecutionIfMemoryLimitIsNotReached() + public function testOnPostMessageReceivedShouldNotInterruptExecutionIfMemoryLimitIsNotReached() { - $context = $this->createContext(); + $postReceivedMessage = new PostMessageReceived( + $this->createInteropContextMock(), + $this->createMock(Message::class), + 'aResult', + 1, + new NullLogger() + ); // guard - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postReceivedMessage->isExecutionInterrupted()); // test $extension = new LimitConsumerMemoryExtension(PHP_INT_MAX); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postReceivedMessage->isExecutionInterrupted()); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function createInteropContextMock(): Context + { + return $this->createMock(Context::class); } /** - * @return Context + * @return \PHPUnit_Framework_MockObject_MockObject */ - protected function createContext(): Context + private function createSubscriptionConsumerMock(): SubscriptionConsumer { - $context = new Context($this->createMock(InteropContext::class)); - $context->setLogger($this->createMock(LoggerInterface::class)); - $context->setConsumer($this->createMock(Consumer::class)); - $context->setProcessor($this->createMock(Processor::class)); + return $this->createMock(SubscriptionConsumer::class); + } - return $context; + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createLoggerMock(): LoggerInterface + { + return $this->createMock(LoggerInterface::class); } } diff --git a/pkg/enqueue/Tests/Consumption/Extension/LimitConsumptionTimeExtensionTest.php b/pkg/enqueue/Tests/Consumption/Extension/LimitConsumptionTimeExtensionTest.php index 66485dc7a..fe0cb5e89 100644 --- a/pkg/enqueue/Tests/Consumption/Extension/LimitConsumptionTimeExtensionTest.php +++ b/pkg/enqueue/Tests/Consumption/Extension/LimitConsumptionTimeExtensionTest.php @@ -2,13 +2,16 @@ namespace Enqueue\Tests\Consumption\Extension; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\PostConsume; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\PreConsume; use Enqueue\Consumption\Extension\LimitConsumptionTimeExtension; -use Interop\Queue\Consumer; -use Interop\Queue\Context as InteropContext; -use Interop\Queue\Processor; +use Interop\Queue\Context; +use Interop\Queue\Message; +use Interop\Queue\SubscriptionConsumer; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; class LimitConsumptionTimeExtensionTest extends TestCase { @@ -17,9 +20,16 @@ public function testCouldBeConstructedWithRequiredArguments() new LimitConsumptionTimeExtension(new \DateTime('+1 day')); } - public function testOnBeforeReceiveShouldInterruptExecutionIfConsumptionTimeExceeded() + public function testOnPreConsumeShouldInterruptExecutionIfConsumptionTimeExceeded() { - $context = $this->createContext(); + $context = new PreConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + new NullLogger(), + 1, + 2, + 3 + ); // guard $this->assertFalse($context->isExecutionInterrupted()); @@ -27,44 +37,64 @@ public function testOnBeforeReceiveShouldInterruptExecutionIfConsumptionTimeExce // test $extension = new LimitConsumptionTimeExtension(new \DateTime('-2 second')); - $extension->onBeforeReceive($context); + $extension->onPreConsume($context); $this->assertTrue($context->isExecutionInterrupted()); } - public function testOnIdleShouldInterruptExecutionIfConsumptionTimeExceeded() + public function testOnPostConsumeShouldInterruptExecutionIfConsumptionTimeExceeded() { - $context = $this->createContext(); + $postConsume = new PostConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + 1, + 1, + 1, + new NullLogger() + ); // guard - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postConsume->isExecutionInterrupted()); // test $extension = new LimitConsumptionTimeExtension(new \DateTime('-2 second')); - $extension->onIdle($context); + $extension->onPostConsume($postConsume); - $this->assertTrue($context->isExecutionInterrupted()); + $this->assertTrue($postConsume->isExecutionInterrupted()); } public function testOnPostReceivedShouldInterruptExecutionIfConsumptionTimeExceeded() { - $context = $this->createContext(); + $postReceivedMessage = new PostMessageReceived( + $this->createInteropContextMock(), + $this->createMock(Message::class), + 'aResult', + 1, + new NullLogger() + ); // guard - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postReceivedMessage->isExecutionInterrupted()); // test $extension = new LimitConsumptionTimeExtension(new \DateTime('-2 second')); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); - $this->assertTrue($context->isExecutionInterrupted()); + $this->assertTrue($postReceivedMessage->isExecutionInterrupted()); } - public function testOnBeforeReceiveShouldNotInterruptExecutionIfConsumptionTimeIsNotExceeded() + public function testOnPreConsumeShouldNotInterruptExecutionIfConsumptionTimeIsNotExceeded() { - $context = $this->createContext(); + $context = new PreConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + new NullLogger(), + 1, + 2, + 3 + ); // guard $this->assertFalse($context->isExecutionInterrupted()); @@ -72,51 +102,75 @@ public function testOnBeforeReceiveShouldNotInterruptExecutionIfConsumptionTimeI // test $extension = new LimitConsumptionTimeExtension(new \DateTime('+2 second')); - $extension->onBeforeReceive($context); + $extension->onPreConsume($context); $this->assertFalse($context->isExecutionInterrupted()); } - public function testOnIdleShouldNotInterruptExecutionIfConsumptionTimeIsNotExceeded() + public function testOnPostConsumeShouldNotInterruptExecutionIfConsumptionTimeIsNotExceeded() { - $context = $this->createContext(); + $postConsume = new PostConsume( + $this->createInteropContextMock(), + $this->createSubscriptionConsumerMock(), + 1, + 1, + 1, + new NullLogger() + ); // guard - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postConsume->isExecutionInterrupted()); // test $extension = new LimitConsumptionTimeExtension(new \DateTime('+2 second')); - $extension->onIdle($context); + $extension->onPostConsume($postConsume); - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postConsume->isExecutionInterrupted()); } public function testOnPostReceivedShouldNotInterruptExecutionIfConsumptionTimeIsNotExceeded() { - $context = $this->createContext(); + $postReceivedMessage = new PostMessageReceived( + $this->createInteropContextMock(), + $this->createMock(Message::class), + 'aResult', + 1, + new NullLogger() + ); // guard - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postReceivedMessage->isExecutionInterrupted()); // test $extension = new LimitConsumptionTimeExtension(new \DateTime('+2 second')); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); - $this->assertFalse($context->isExecutionInterrupted()); + $this->assertFalse($postReceivedMessage->isExecutionInterrupted()); } /** - * @return Context + * @return \PHPUnit_Framework_MockObject_MockObject */ - protected function createContext(): Context + protected function createInteropContextMock(): Context { - $context = new Context($this->createMock(InteropContext::class)); - $context->setLogger($this->createMock(LoggerInterface::class)); - $context->setConsumer($this->createMock(Consumer::class)); - $context->setProcessor($this->createMock(Processor::class)); + return $this->createMock(Context::class); + } - return $context; + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createSubscriptionConsumerMock(): SubscriptionConsumer + { + return $this->createMock(SubscriptionConsumer::class); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createLoggerMock(): LoggerInterface + { + return $this->createMock(LoggerInterface::class); } } diff --git a/pkg/enqueue/Tests/Consumption/Extension/LoggerExtensionTest.php b/pkg/enqueue/Tests/Consumption/Extension/LoggerExtensionTest.php index 6bd05ef8c..37ef696d8 100644 --- a/pkg/enqueue/Tests/Consumption/Extension/LoggerExtensionTest.php +++ b/pkg/enqueue/Tests/Consumption/Extension/LoggerExtensionTest.php @@ -2,24 +2,33 @@ namespace Enqueue\Tests\Consumption\Extension; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\Start; use Enqueue\Consumption\Extension\LoggerExtension; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\PostMessageReceivedExtensionInterface; use Enqueue\Consumption\Result; +use Enqueue\Consumption\StartExtensionInterface; use Enqueue\Null\NullMessage; use Enqueue\Test\ClassExtensionTrait; use Interop\Queue\Consumer; use Interop\Queue\Context as InteropContext; +use Interop\Queue\Message; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; class LoggerExtensionTest extends TestCase { use ClassExtensionTrait; - public function testShouldImplementExtensionInterface() + public function testShouldImplementStartExtensionInterface() { - $this->assertClassImplements(ExtensionInterface::class, LoggerExtension::class); + $this->assertClassImplements(StartExtensionInterface::class, LoggerExtension::class); + } + + public function testShouldImplementPostMessageReceivedExtensionInterface() + { + $this->assertClassImplements(PostMessageReceivedExtensionInterface::class, LoggerExtension::class); } public function testCouldBeConstructedWithLoggerAsFirstArgument() @@ -33,7 +42,7 @@ public function testShouldSetLoggerToContextOnStart() $extension = new LoggerExtension($logger); - $context = new Context($this->createContextMock()); + $context = new Start($this->createContextMock(), new NullLogger(), [], 0, 0); $extension->onStart($context); @@ -51,7 +60,7 @@ public function testShouldAddInfoMessageOnStart() $extension = new LoggerExtension($logger); - $context = new Context($this->createContextMock()); + $context = new Start($this->createContextMock(), new NullLogger(), [], 0, 0); $extension->onStart($context); } @@ -70,11 +79,15 @@ public function testShouldLogRejectMessageStatus() $message = new NullMessage(); $message->setBody('message body'); - $context = new Context($this->createContextMock()); - $context->setResult(Result::reject('reason')); - $context->setInteropMessage($message); + $postReceivedMessage = new PostMessageReceived( + $this->createContextMock(), + $message, + Result::reject('reason'), + 1, + $logger + ); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); } public function testShouldLogRequeueMessageStatus() @@ -91,11 +104,15 @@ public function testShouldLogRequeueMessageStatus() $message = new NullMessage(); $message->setBody('message body'); - $context = new Context($this->createContextMock()); - $context->setResult(Result::requeue('reason')); - $context->setInteropMessage($message); + $postReceivedMessage = new PostMessageReceived( + $this->createContextMock(), + $message, + Result::requeue('reason'), + 1, + $logger + ); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); } public function testShouldNotLogRequeueMessageStatusIfReasonIsEmpty() @@ -108,10 +125,15 @@ public function testShouldNotLogRequeueMessageStatusIfReasonIsEmpty() $extension = new LoggerExtension($logger); - $context = new Context($this->createContextMock()); - $context->setResult(Result::requeue()); + $postReceivedMessage = new PostMessageReceived( + $this->createContextMock(), + $this->createMock(Message::class), + Result::requeue(), + 1, + $logger + ); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); } public function testShouldLogAckMessageStatus() @@ -128,11 +150,15 @@ public function testShouldLogAckMessageStatus() $message = new NullMessage(); $message->setBody('message body'); - $context = new Context($this->createContextMock()); - $context->setResult(Result::ack('reason')); - $context->setInteropMessage($message); + $postReceivedMessage = new PostMessageReceived( + $this->createContextMock(), + $message, + Result::ack('reason'), + 1, + $logger + ); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); } public function testShouldNotLogAckMessageStatusIfReasonIsEmpty() @@ -145,10 +171,15 @@ public function testShouldNotLogAckMessageStatusIfReasonIsEmpty() $extension = new LoggerExtension($logger); - $context = new Context($this->createContextMock()); - $context->setResult(Result::ack()); + $postReceivedMessage = new PostMessageReceived( + $this->createContextMock(), + $this->createMock(Message::class), + Result::ack(), + 1, + $logger + ); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); } public function testShouldNotSetLoggerIfOneHasBeenSetOnStart() @@ -168,8 +199,7 @@ public function testShouldNotSetLoggerIfOneHasBeenSetOnStart() $extension = new LoggerExtension($logger); - $context = new Context($this->createContextMock()); - $context->setLogger($alreadySetLogger); + $context = new Start($this->createContextMock(), $alreadySetLogger, [], 0, 0); $extension->onStart($context); } diff --git a/pkg/enqueue/Tests/Consumption/Extension/NicenessExtensionTest.php b/pkg/enqueue/Tests/Consumption/Extension/NicenessExtensionTest.php index 36a80d38b..5b1834a88 100644 --- a/pkg/enqueue/Tests/Consumption/Extension/NicenessExtensionTest.php +++ b/pkg/enqueue/Tests/Consumption/Extension/NicenessExtensionTest.php @@ -2,13 +2,11 @@ namespace Enqueue\Tests\Consumption\Extension; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\Start; use Enqueue\Consumption\Extension\NicenessExtension; -use Interop\Queue\Consumer; use Interop\Queue\Context as InteropContext; -use Interop\Queue\Processor; use PHPUnit\Framework\TestCase; -use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; class NicenessExtensionTest extends TestCase { @@ -28,20 +26,17 @@ public function testShouldThrowWarningOnInvalidArgument() $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('proc_nice(): Only a super user may attempt to increase the priority of a process'); + $context = new Start($this->createContextMock(), new NullLogger(), [], 0, 0); + $extension = new NicenessExtension(-1); - $extension->onStart($this->createContext()); + $extension->onStart($context); } /** - * @return Context + * @return \PHPUnit_Framework_MockObject_MockObject|InteropContext */ - protected function createContext(): Context + protected function createContextMock(): InteropContext { - $context = new Context($this->createMock(InteropContext::class)); - $context->setLogger($this->createMock(LoggerInterface::class)); - $context->setConsumer($this->createMock(Consumer::class)); - $context->setProcessor($this->createMock(Processor::class)); - - return $context; + return $this->createMock(InteropContext::class); } } diff --git a/pkg/enqueue/Tests/Consumption/Extension/ReplyExtensionTest.php b/pkg/enqueue/Tests/Consumption/Extension/ReplyExtensionTest.php index 09802d3f1..e78a7451f 100644 --- a/pkg/enqueue/Tests/Consumption/Extension/ReplyExtensionTest.php +++ b/pkg/enqueue/Tests/Consumption/Extension/ReplyExtensionTest.php @@ -2,14 +2,14 @@ namespace Enqueue\Tests\Consumption\Extension; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\PostMessageReceived; use Enqueue\Consumption\Extension\ReplyExtension; -use Enqueue\Consumption\ExtensionInterface; +use Enqueue\Consumption\PostMessageReceivedExtensionInterface; use Enqueue\Consumption\Result; use Enqueue\Null\NullMessage; use Enqueue\Null\NullQueue; use Enqueue\Test\ClassExtensionTrait; -use Interop\Queue\Context as InteropContext; +use Interop\Queue\Context; use Interop\Queue\Producer as InteropProducer; use PHPUnit\Framework\TestCase; use Psr\Log\NullLogger; @@ -18,9 +18,9 @@ class ReplyExtensionTest extends TestCase { use ClassExtensionTrait; - public function testShouldImplementExtensionInterface() + public function testShouldImplementPostMessageReceivedExtensionInterface() { - $this->assertClassImplements(ExtensionInterface::class, ReplyExtension::class); + $this->assertClassImplements(PostMessageReceivedExtensionInterface::class, ReplyExtension::class); } public function testCouldBeConstructedWithoutAnyArguments() @@ -28,42 +28,19 @@ public function testCouldBeConstructedWithoutAnyArguments() new ReplyExtension(); } - public function testShouldDoNothingOnPreReceived() - { - $extension = new ReplyExtension(); - - $extension->onPreReceived(new Context($this->createNeverUsedContextMock())); - } - - public function testShouldDoNothingOnStart() - { - $extension = new ReplyExtension(); - - $extension->onStart(new Context($this->createNeverUsedContextMock())); - } - - public function testShouldDoNothingOnBeforeReceive() - { - $extension = new ReplyExtension(); - - $extension->onBeforeReceive(new Context($this->createNeverUsedContextMock())); - } - - public function testShouldDoNothingOnInterrupted() - { - $extension = new ReplyExtension(); - - $extension->onInterrupted(new Context($this->createNeverUsedContextMock())); - } - public function testShouldDoNothingIfReceivedMessageNotHaveReplyToSet() { $extension = new ReplyExtension(); - $context = new Context($this->createNeverUsedContextMock()); - $context->setInteropMessage(new NullMessage()); + $postReceivedMessage = new PostMessageReceived( + $this->createNeverUsedContextMock(), + new NullMessage(), + 'aResult', + 1, + new NullLogger() + ); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); } public function testShouldDoNothingIfContextResultIsNotInstanceOfResult() @@ -73,11 +50,15 @@ public function testShouldDoNothingIfContextResultIsNotInstanceOfResult() $message = new NullMessage(); $message->setReplyTo('aReplyToQueue'); - $context = new Context($this->createNeverUsedContextMock()); - $context->setInteropMessage($message); - $context->setResult('notInstanceOfResult'); + $postReceivedMessage = new PostMessageReceived( + $this->createNeverUsedContextMock(), + $message, + 'notInstanceOfResult', + 1, + new NullLogger() + ); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); } public function testShouldDoNothingIfResultInstanceOfResultButReplyMessageNotSet() @@ -87,11 +68,15 @@ public function testShouldDoNothingIfResultInstanceOfResultButReplyMessageNotSet $message = new NullMessage(); $message->setReplyTo('aReplyToQueue'); - $context = new Context($this->createNeverUsedContextMock()); - $context->setInteropMessage($message); - $context->setResult(Result::ack()); + $postReceivedMessage = new PostMessageReceived( + $this->createNeverUsedContextMock(), + $message, + Result::ack(), + 1, + new NullLogger() + ); - $extension->onPostReceived($context); + $extension->onPostMessageReceived($postReceivedMessage); } public function testShouldSendReplyMessageToReplyQueueOnPostReceived() @@ -114,8 +99,8 @@ public function testShouldSendReplyMessageToReplyQueueOnPostReceived() ->with($replyQueue, $replyMessage) ; - /** @var \PHPUnit_Framework_MockObject_MockObject|InteropContext $contextMock */ - $contextMock = $this->createMock(InteropContext::class); + /** @var \PHPUnit_Framework_MockObject_MockObject|Context $contextMock */ + $contextMock = $this->createMock(Context::class); $contextMock ->expects($this->once()) ->method('createQueue') @@ -127,20 +112,31 @@ public function testShouldSendReplyMessageToReplyQueueOnPostReceived() ->willReturn($producerMock) ; - $context = new Context($contextMock); - $context->setInteropMessage($message); - $context->setResult(Result::reply($replyMessage)); - $context->setLogger(new NullLogger()); + $postReceivedMessage = new PostMessageReceived( + $contextMock, + $message, + Result::reply($replyMessage), + 1, + new NullLogger() + ); + + $extension->onPostMessageReceived($postReceivedMessage); + } - $extension->onPostReceived($context); + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function createInteropContextMock(): Context + { + return $this->createMock(Context::class); } /** - * @return \PHPUnit_Framework_MockObject_MockObject|InteropContext + * @return \PHPUnit_Framework_MockObject_MockObject */ - private function createNeverUsedContextMock(): InteropContext + private function createNeverUsedContextMock(): Context { - $contextMock = $this->createMock(InteropContext::class); + $contextMock = $this->createMock(Context::class); $contextMock ->expects($this->never()) ->method('createProducer') diff --git a/pkg/enqueue/Tests/Consumption/Mock/BreakCycleExtension.php b/pkg/enqueue/Tests/Consumption/Mock/BreakCycleExtension.php index b61d8dd8d..831c7a901 100644 --- a/pkg/enqueue/Tests/Consumption/Mock/BreakCycleExtension.php +++ b/pkg/enqueue/Tests/Consumption/Mock/BreakCycleExtension.php @@ -2,14 +2,19 @@ namespace Enqueue\Tests\Consumption\Mock; -use Enqueue\Consumption\Context; -use Enqueue\Consumption\EmptyExtensionTrait; +use Enqueue\Consumption\Context\End; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\Context\MessageResult; +use Enqueue\Consumption\Context\PostConsume; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\PreConsume; +use Enqueue\Consumption\Context\PreSubscribe; +use Enqueue\Consumption\Context\ProcessorException; +use Enqueue\Consumption\Context\Start; use Enqueue\Consumption\ExtensionInterface; class BreakCycleExtension implements ExtensionInterface { - use EmptyExtensionTrait; - protected $cycles = 1; private $limit; @@ -19,15 +24,47 @@ public function __construct($limit) $this->limit = $limit; } - public function onPostReceived(Context $context) + public function onPostMessageReceived(PostMessageReceived $context): void + { + if ($this->cycles >= $this->limit) { + $context->interruptExecution(); + } else { + ++$this->cycles; + } + } + + public function onEnd(End $context): void + { + } + + public function onMessageReceived(MessageReceived $context): void + { + } + + public function onResult(MessageResult $context): void + { + } + + public function onPreConsume(PreConsume $context): void + { + } + + public function onPreSubscribe(PreSubscribe $context): void + { + } + + public function onProcessorException(ProcessorException $context): void + { + } + + public function onStart(Start $context): void { - $this->onIdle($context); } - public function onIdle(Context $context) + public function onPostConsume(PostConsume $context): void { if ($this->cycles >= $this->limit) { - $context->setExecutionInterrupted(true); + $context->interruptExecution(); } else { ++$this->cycles; } diff --git a/pkg/enqueue/Tests/Consumption/QueueConsumerTest.php b/pkg/enqueue/Tests/Consumption/QueueConsumerTest.php index 5b655c13e..50ced5ef6 100644 --- a/pkg/enqueue/Tests/Consumption/QueueConsumerTest.php +++ b/pkg/enqueue/Tests/Consumption/QueueConsumerTest.php @@ -2,9 +2,18 @@ namespace Enqueue\Tests\Consumption; +use Enqueue\Consumption\BoundProcessor; use Enqueue\Consumption\CallbackProcessor; use Enqueue\Consumption\ChainExtension; -use Enqueue\Consumption\Context; +use Enqueue\Consumption\Context\End; +use Enqueue\Consumption\Context\MessageReceived; +use Enqueue\Consumption\Context\MessageResult; +use Enqueue\Consumption\Context\PostConsume; +use Enqueue\Consumption\Context\PostMessageReceived; +use Enqueue\Consumption\Context\PreConsume; +use Enqueue\Consumption\Context\PreSubscribe; +use Enqueue\Consumption\Context\ProcessorException; +use Enqueue\Consumption\Context\Start; use Enqueue\Consumption\Exception\InvalidArgumentException; use Enqueue\Consumption\ExtensionInterface; use Enqueue\Consumption\QueueConsumer; @@ -20,46 +29,75 @@ use Interop\Queue\Queue; use Interop\Queue\SubscriptionConsumer; use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; class QueueConsumerTest extends TestCase { - public function testCouldBeConstructedWithConnectionAndExtensionsAsArguments() + public function testCouldBeConstructedWithAllArguments() { - new QueueConsumer($this->createContextStub(), null, 0); + new QueueConsumer($this->createContextStub(), null, [], null, 0); } - public function testCouldBeConstructedWithConnectionOnly() + public function testCouldBeConstructedWithContextOnly() { new QueueConsumer($this->createContextStub()); } - public function testCouldBeConstructedWithConnectionAndSingleExtension() + public function testCouldBeConstructedWithContextAndSingleExtension() { new QueueConsumer($this->createContextStub(), $this->createExtension()); } public function testShouldSetEmptyArrayToBoundProcessorsPropertyInConstructor() { - $consumer = new QueueConsumer($this->createContextStub(), null, 0); + $consumer = new QueueConsumer($this->createContextStub(), null, [], null, 0); $this->assertAttributeSame([], 'boundProcessors', $consumer); } - public function testShouldAllowGetConnectionSetInConstructor() + public function testShouldSetProvidedBoundProcessorsToThePropertyInConstructor() { - $expectedConnection = $this->createContextStub(); + $boundProcessors = [ + new BoundProcessor(new NullQueue('foo'), $this->createProcessorMock()), + new BoundProcessor(new NullQueue('bar'), $this->createProcessorMock()), + ]; + + $consumer = new QueueConsumer($this->createContextStub(), null, $boundProcessors, null, 0); + + $this->assertAttributeSame($boundProcessors, 'boundProcessors', $consumer); + } + + public function testShouldSetNullLoggerIfNoneProvidedInConstructor() + { + $consumer = new QueueConsumer($this->createContextStub(), null, [], null, 0); + + $this->assertAttributeInstanceOf(NullLogger::class, 'logger', $consumer); + } + + public function testShouldSetProvidedLoggerToThePropertyInConstructor() + { + $expectedLogger = $this->createMock(LoggerInterface::class); + + $consumer = new QueueConsumer($this->createContextStub(), null, [], $expectedLogger, 0); + + $this->assertAttributeSame($expectedLogger, 'logger', $consumer); + } + + public function testShouldAllowGetContextSetInConstructor() + { + $expectedContext = $this->createContextStub(); - $consumer = new QueueConsumer($expectedConnection, null, 0); + $consumer = new QueueConsumer($expectedContext, null, [], null, 0); - $this->assertSame($expectedConnection, $consumer->getContext()); + $this->assertSame($expectedContext, $consumer->getContext()); } public function testThrowIfQueueNameEmptyOnBind() { $processorMock = $this->createProcessorMock(); - $consumer = new QueueConsumer($this->createContextStub(), null, 0); + $consumer = new QueueConsumer($this->createContextStub()); $this->expectException(\LogicException::class); $this->expectExceptionMessage('The queue name must be not empty.'); @@ -70,7 +108,7 @@ public function testThrowIfQueueAlreadyBoundToProcessorOnBind() { $processorMock = $this->createProcessorMock(); - $consumer = new QueueConsumer($this->createContextStub(), null, 0); + $consumer = new QueueConsumer($this->createContextStub()); $consumer->bind(new NullQueue('theQueueName'), $processorMock); @@ -84,40 +122,35 @@ public function testShouldAllowBindProcessorToQueue() $queue = new NullQueue('theQueueName'); $processorMock = $this->createProcessorMock(); - $consumer = new QueueConsumer($this->createContextStub(), null, 0); + $consumer = new QueueConsumer($this->createContextStub()); $consumer->bind($queue, $processorMock); - $this->assertAttributeSame(['theQueueName' => [$queue, $processorMock]], 'boundProcessors', $consumer); + $this->assertAttributeEquals( + ['theQueueName' => new BoundProcessor($queue, $processorMock)], + 'boundProcessors', + $consumer + ); } public function testThrowIfQueueNeitherInstanceOfQueueNorString() { $processorMock = $this->createProcessorMock(); - $consumer = new QueueConsumer($this->createContextStub(), null, 0); + $consumer = new QueueConsumer($this->createContextStub()); $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('The argument must be an instance of Interop\Queue\Queue but got stdClass.'); $consumer->bind(new \stdClass(), $processorMock); } - public function testCouldSetGetIdleTimeout() - { - $consumer = new QueueConsumer($this->createContextStub(), null, 0); - - $consumer->setIdleTimeout(123456.1); - - $this->assertSame(123456.1, $consumer->getIdleTimeout()); - } - public function testCouldSetGetReceiveTimeout() { - $consumer = new QueueConsumer($this->createContextStub(), null, 0); + $consumer = new QueueConsumer($this->createContextStub()); - $consumer->setReceiveTimeout(123456.1); + $consumer->setReceiveTimeout(123456); - $this->assertSame(123456.1, $consumer->getReceiveTimeout()); + $this->assertSame(123456, $consumer->getReceiveTimeout()); } public function testShouldAllowBindCallbackToQueueName() @@ -136,7 +169,7 @@ public function testShouldAllowBindCallbackToQueueName() ->willReturn($queue) ; - $consumer = new QueueConsumer($context, null, 0); + $consumer = new QueueConsumer($context); $consumer->bindCallback($queueName, $callback); @@ -146,17 +179,16 @@ public function testShouldAllowBindCallbackToQueueName() $this->assertCount(1, $boundProcessors); $this->assertArrayHasKey($queueName, $boundProcessors); - $this->assertInternalType('array', $boundProcessors[$queueName]); - $this->assertCount(2, $boundProcessors[$queueName]); - $this->assertSame($queue, $boundProcessors[$queueName][0]); - $this->assertInstanceOf(CallbackProcessor::class, $boundProcessors[$queueName][1]); + $this->assertInstanceOf(BoundProcessor::class, $boundProcessors[$queueName]); + $this->assertSame($queue, $boundProcessors[$queueName]->getQueue()); + $this->assertInstanceOf(CallbackProcessor::class, $boundProcessors[$queueName]->getProcessor()); } public function testShouldReturnSelfOnBind() { $processorMock = $this->createProcessorMock(); - $consumer = new QueueConsumer($this->createContextStub(), null, 0); + $consumer = new QueueConsumer($this->createContextStub()); $this->assertSame($consumer, $consumer->bind(new NullQueue('foo_queue'), $processorMock)); } @@ -271,13 +303,13 @@ public function testShouldSubscribeToGivenQueueWithExpectedTimeout() ->method('process') ; - $queueConsumer = new QueueConsumer($contextMock, new BreakCycleExtension(1), 0, 12345); + $queueConsumer = new QueueConsumer($contextMock, new BreakCycleExtension(1), [], null, 12345); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind($expectedQueue, $processorMock); $queueConsumer->consume(); } - public function testShouldSubscribeToGivenQueueAndQuitAfterFifthIdleCycle() + public function testShouldSubscribeToGivenQueueAndQuitAfterFifthConsumeCycle() { $expectedQueue = new NullQueue('theQueueName'); @@ -302,7 +334,7 @@ public function testShouldSubscribeToGivenQueueAndQuitAfterFifthIdleCycle() ->method('process') ; - $queueConsumer = new QueueConsumer($contextMock, new BreakCycleExtension(5), 0); + $queueConsumer = new QueueConsumer($contextMock, new BreakCycleExtension(5)); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind($expectedQueue, $processorMock); $queueConsumer->consume(); @@ -365,7 +397,7 @@ public function testShouldAckMessageIfProcessorReturnSuchStatus() ->willReturn(Result::ACK) ; - $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1), 0); + $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1)); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); @@ -391,7 +423,7 @@ public function testThrowIfProcessorReturnNull() ->willReturn(null) ; - $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1), 0); + $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1)); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); @@ -424,7 +456,41 @@ public function testShouldRejectMessageIfProcessorReturnSuchStatus() ->willReturn(Result::REJECT) ; - $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1), 0); + $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1)); + $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); + $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); + + $queueConsumer->consume(); + } + + public function testShouldDoNothingIfProcessorReturnsAlreadyAcknowledged() + { + $messageMock = $this->createMessageMock(); + + $subscriptionConsumerMock = new DummySubscriptionConsumer(); + $subscriptionConsumerMock->addMessage($messageMock, 'foo_queue'); + + $consumerStub = $this->createConsumerStub('foo_queue'); + $consumerStub + ->expects($this->never()) + ->method('reject') + ; + $consumerStub + ->expects($this->never()) + ->method('acknowledge') + ; + + $contextStub = $this->createContextStub($consumerStub); + + $processorMock = $this->createProcessorMock(); + $processorMock + ->expects($this->once()) + ->method('process') + ->with($this->identicalTo($messageMock)) + ->willReturn(Result::ALREADY_ACKNOWLEDGED) + ; + + $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1)); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); @@ -455,7 +521,7 @@ public function testShouldRequeueMessageIfProcessorReturnSuchStatus() ->willReturn(Result::REQUEUE) ; - $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1), 0); + $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1)); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); @@ -481,7 +547,7 @@ public function testThrowIfProcessorReturnInvalidStatus() ->willReturn('invalidStatus') ; - $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1), 0); + $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1)); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); @@ -495,10 +561,10 @@ public function testShouldNotPassMessageToProcessorIfItWasProcessedByExtension() $extension = $this->createExtension(); $extension ->expects($this->once()) - ->method('onPreReceived') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) { - $context->setResult(Result::ACK); + ->method('onMessageReceived') + ->with($this->isInstanceOf(MessageReceived::class)) + ->willReturnCallback(function (MessageReceived $context) { + $context->setResult(Result::ack()); }) ; @@ -518,7 +584,7 @@ public function testShouldNotPassMessageToProcessorIfItWasProcessedByExtension() ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); @@ -537,29 +603,22 @@ public function testShouldCallOnStartExtensionMethod() $extension ->expects($this->once()) ->method('onStart') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ($contextStub) { - $this->assertSame($contextStub, $context->getInteropContext()); - $this->assertNull($context->getConsumer()); - $this->assertNull($context->getProcessor()); - $this->assertNull($context->getLogger()); - $this->assertNull($context->getInteropMessage()); - $this->assertNull($context->getException()); - $this->assertNull($context->getResult()); - $this->assertNull($context->getInteropQueue()); - $this->assertFalse($context->isExecutionInterrupted()); + ->with($this->isInstanceOf(Start::class)) + ->willReturnCallback(function (Start $context) use ($contextStub) { + $this->assertSame($contextStub, $context->getContext()); + $this->assertInstanceOf(NullLogger::class, $context->getLogger()); }) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); $queueConsumer->setFallbackSubscriptionConsumer(new DummySubscriptionConsumer()); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); $queueConsumer->consume(); } - public function testShouldCallOnIdleExtensionMethod() + public function testShouldCallOnStartWithLoggerProvidedInConstructor() { $consumerStub = $this->createConsumerStub('foo_queue'); @@ -567,349 +626,380 @@ public function testShouldCallOnIdleExtensionMethod() $processorMock = $this->createProcessorMock(); + $expectedLogger = $this->createMock(LoggerInterface::class); + $extension = $this->createExtension(); $extension ->expects($this->once()) - ->method('onIdle') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ($contextStub) { - $this->assertSame($contextStub, $context->getInteropContext()); - $this->assertInstanceOf(NullLogger::class, $context->getLogger()); - $this->assertNull($context->getProcessor()); - $this->assertNull($context->getConsumer()); - $this->assertNull($context->getInteropMessage()); - $this->assertNull($context->getException()); - $this->assertNull($context->getResult()); - $this->assertFalse($context->isExecutionInterrupted()); + ->method('onStart') + ->with($this->isInstanceOf(Start::class)) + ->willReturnCallback(function (Start $context) use ($expectedLogger) { + $this->assertSame($expectedLogger, $context->getLogger()); }) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, [], $expectedLogger); $queueConsumer->setFallbackSubscriptionConsumer(new DummySubscriptionConsumer()); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); $queueConsumer->consume(); } - public function testShouldCallOnBeforeReceiveExtensionMethod() + public function testShouldInterruptExecutionOnStart() { $consumerStub = $this->createConsumerStub('foo_queue'); $contextStub = $this->createContextStub($consumerStub); - $processorMock = $this->createProcessorStub(); + $processorMock = $this->createProcessorMock(); + $processorMock + ->expects($this->never()) + ->method('process') + ; - $queue = new NullQueue('foo_queue'); + $expectedLogger = $this->createMock(LoggerInterface::class); $extension = $this->createExtension(); $extension ->expects($this->once()) - ->method('onBeforeReceive') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ($contextStub) { - $this->assertSame($contextStub, $context->getInteropContext()); - $this->assertInstanceOf(NullLogger::class, $context->getLogger()); - $this->assertNull($context->getProcessor()); - $this->assertNull($context->getConsumer()); - $this->assertNull($context->getInteropMessage()); - $this->assertNull($context->getException()); - $this->assertNull($context->getResult()); - $this->assertNull($context->getInteropQueue()); - $this->assertFalse($context->isExecutionInterrupted()); + ->method('onStart') + ->willReturnCallback(function (Start $context) { + $context->interruptExecution(); }) ; + $extension + ->expects($this->once()) + ->method('onEnd') + ; + $extension + ->expects($this->never()) + ->method('onPreConsume') + ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, [], $expectedLogger); $queueConsumer->setFallbackSubscriptionConsumer(new DummySubscriptionConsumer()); - $queueConsumer->bind($queue, $processorMock); + $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); $queueConsumer->consume(); } - public function testShouldCallOnPreReceivedExtensionMethodWithExpectedContext() + public function testShouldCallPreSubscribeExtensionMethod() { - $expectedMessage = $this->createMessageMock(); - - $subscriptionConsumerMock = new DummySubscriptionConsumer(); - $subscriptionConsumerMock->addMessage($expectedMessage, 'foo_queue'); - $consumerStub = $this->createConsumerStub('foo_queue'); $contextStub = $this->createContextStub($consumerStub); - $processorMock = $this->createProcessorStub(); + $processorMock = $this->createProcessorMock(); $extension = $this->createExtension(); $extension ->expects($this->once()) - ->method('onPreReceived') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ( - $contextStub, - $consumerStub, - $processorMock, - $expectedMessage - ) { - $this->assertSame($contextStub, $context->getInteropContext()); + ->method('onPreSubscribe') + ->with($this->isInstanceOf(PreSubscribe::class)) + ->willReturnCallback(function (PreSubscribe $context) use ($contextStub, $consumerStub, $processorMock) { + $this->assertSame($contextStub, $context->getContext()); $this->assertSame($consumerStub, $context->getConsumer()); $this->assertSame($processorMock, $context->getProcessor()); - $this->assertSame($expectedMessage, $context->getInteropMessage()); $this->assertInstanceOf(NullLogger::class, $context->getLogger()); - $this->assertNull($context->getException()); - $this->assertNull($context->getResult()); - $this->assertFalse($context->isExecutionInterrupted()); }) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); - $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); + $queueConsumer->setFallbackSubscriptionConsumer(new DummySubscriptionConsumer()); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); $queueConsumer->consume(); } - public function testShouldCallOnResultExtensionMethodWithExpectedContext() + public function testShouldCallPreSubscribeForEachBoundProcessor() { - $expectedMessage = $this->createMessageMock(); + $consumerStub = $this->createConsumerStub('foo_queue'); - $subscriptionConsumerMock = new DummySubscriptionConsumer(); - $subscriptionConsumerMock->addMessage($expectedMessage, 'foo_queue'); + $contextStub = $this->createContextStub($consumerStub); + + $processorMock = $this->createProcessorMock(); + + $extension = $this->createExtension(); + $extension + ->expects($this->exactly(3)) + ->method('onPreSubscribe') + ->with($this->isInstanceOf(PreSubscribe::class)) + ; + + $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); + $queueConsumer->setFallbackSubscriptionConsumer(new DummySubscriptionConsumer()); + $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); + $queueConsumer->bind(new NullQueue('bar_queue'), $processorMock); + $queueConsumer->bind(new NullQueue('baz_queue'), $processorMock); + + $queueConsumer->consume(); + } + public function testShouldCallOnPostConsumeExtensionMethod() + { $consumerStub = $this->createConsumerStub('foo_queue'); $contextStub = $this->createContextStub($consumerStub); - $processorMock = $this->createProcessorStub(); + $subscriptionConsumer = new DummySubscriptionConsumer(); + + $processorMock = $this->createProcessorMock(); $extension = $this->createExtension(); $extension ->expects($this->once()) - ->method('onResult') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ( - $contextStub, - $consumerStub, - $processorMock, - $expectedMessage - ) { - $this->assertSame($contextStub, $context->getInteropContext()); - $this->assertSame($consumerStub, $context->getConsumer()); - $this->assertSame($processorMock, $context->getProcessor()); - $this->assertSame($expectedMessage, $context->getInteropMessage()); + ->method('onPostConsume') + ->with($this->isInstanceOf(PostConsume::class)) + ->willReturnCallback(function (PostConsume $context) use ($contextStub, $subscriptionConsumer) { + $this->assertSame($contextStub, $context->getContext()); + $this->assertSame($subscriptionConsumer, $context->getSubscriptionConsumer()); + $this->assertSame(1, $context->getCycle()); + $this->assertSame(0, $context->getReceivedMessagesCount()); + $this->assertGreaterThan(1, $context->getStartTime()); $this->assertInstanceOf(NullLogger::class, $context->getLogger()); - $this->assertNull($context->getException()); - $this->assertSame(Result::ACK, $context->getResult()); $this->assertFalse($context->isExecutionInterrupted()); }) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); - $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); + $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumer); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); $queueConsumer->consume(); } - public function testShouldCallOnPostReceivedExtensionMethodWithExpectedContext() + public function testShouldCallOnPreConsumeExtensionMethod() { - $expectedMessage = $this->createMessageMock(); - - $subscriptionConsumerMock = new DummySubscriptionConsumer(); - $subscriptionConsumerMock->addMessage($expectedMessage, 'foo_queue'); - $consumerStub = $this->createConsumerStub('foo_queue'); $contextStub = $this->createContextStub($consumerStub); $processorMock = $this->createProcessorStub(); + $queue = new NullQueue('foo_queue'); + $extension = $this->createExtension(); $extension ->expects($this->once()) - ->method('onPostReceived') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ( - $contextStub, - $consumerStub, - $processorMock, - $expectedMessage - ) { - $this->assertSame($contextStub, $context->getInteropContext()); - $this->assertSame($consumerStub, $context->getConsumer()); - $this->assertSame($processorMock, $context->getProcessor()); - $this->assertSame($expectedMessage, $context->getInteropMessage()); + ->method('onPreConsume') + ->with($this->isInstanceOf(PreConsume::class)) + ->willReturnCallback(function (PreConsume $context) use ($contextStub) { + $this->assertSame($contextStub, $context->getContext()); $this->assertInstanceOf(NullLogger::class, $context->getLogger()); - $this->assertNull($context->getException()); - $this->assertSame(Result::ACK, $context->getResult()); + $this->assertInstanceOf(SubscriptionConsumer::class, $context->getSubscriptionConsumer()); + $this->assertSame(10000, $context->getReceiveTimeout()); + $this->assertSame(1, $context->getCycle()); + $this->assertGreaterThan(0, $context->getStartTime()); $this->assertFalse($context->isExecutionInterrupted()); }) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); - $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); - $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); + $queueConsumer->setFallbackSubscriptionConsumer(new DummySubscriptionConsumer()); + $queueConsumer->bind($queue, $processorMock); $queueConsumer->consume(); } - public function testShouldAllowInterruptConsumingOnIdle() + public function testShouldCallOnPreConsumeExpectedAmountOfTimes() { $consumerStub = $this->createConsumerStub('foo_queue'); $contextStub = $this->createContextStub($consumerStub); - $processorMock = $this->createProcessorMock(); + $processorMock = $this->createProcessorStub(); + + $queue = new NullQueue('foo_queue'); $extension = $this->createExtension(); $extension - ->expects($this->once()) - ->method('onIdle') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) { - $context->setExecutionInterrupted(true); - }) + ->expects($this->exactly(3)) + ->method('onPreConsume') ; + + $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(3)]); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); + $queueConsumer->setFallbackSubscriptionConsumer(new DummySubscriptionConsumer()); + $queueConsumer->bind($queue, $processorMock); + + $queueConsumer->consume(); + } + + public function testShouldCallOnPreReceivedExtensionMethodWithExpectedContext() + { + $expectedMessage = $this->createMessageMock(); + + $subscriptionConsumerMock = new DummySubscriptionConsumer(); + $subscriptionConsumerMock->addMessage($expectedMessage, 'foo_queue'); + + $consumerStub = $this->createConsumerStub('foo_queue'); + + $contextStub = $this->createContextStub($consumerStub); + + $processorMock = $this->createProcessorStub(); + + $extension = $this->createExtension(); $extension ->expects($this->once()) - ->method('onInterrupted') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ($contextStub) { - $this->assertSame($contextStub, $context->getInteropContext()); + ->method('onMessageReceived') + ->with($this->isInstanceOf(MessageReceived::class)) + ->willReturnCallback(function (MessageReceived $context) use ( + $contextStub, + $consumerStub, + $processorMock, + $expectedMessage + ) { + $this->assertSame($contextStub, $context->getContext()); + $this->assertSame($consumerStub, $context->getConsumer()); + $this->assertSame($processorMock, $context->getProcessor()); + $this->assertSame($expectedMessage, $context->getMessage()); $this->assertInstanceOf(NullLogger::class, $context->getLogger()); - $this->assertNull($context->getConsumer()); - $this->assertNull($context->getProcessor()); - $this->assertNull($context->getInteropMessage()); - $this->assertNull($context->getException()); $this->assertNull($context->getResult()); - $this->assertTrue($context->isExecutionInterrupted()); }) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); - $queueConsumer->setFallbackSubscriptionConsumer(new DummySubscriptionConsumer()); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); + $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); $queueConsumer->consume(); } - public function testShouldNotCloseContextWhenConsumptionInterrupted() + public function testShouldCallOnResultExtensionMethodWithExpectedContext() { + $expectedMessage = $this->createMessageMock(); + + $subscriptionConsumerMock = new DummySubscriptionConsumer(); + $subscriptionConsumerMock->addMessage($expectedMessage, 'foo_queue'); + $consumerStub = $this->createConsumerStub('foo_queue'); $contextStub = $this->createContextStub($consumerStub); - $contextStub - ->expects($this->never()) - ->method('close') - ; - $processorMock = $this->createProcessorMock(); + $processorMock = $this->createProcessorStub(); $extension = $this->createExtension(); $extension ->expects($this->once()) - ->method('onIdle') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) { - $context->setExecutionInterrupted(true); + ->method('onResult') + ->with($this->isInstanceOf(MessageResult::class)) + ->willReturnCallback(function (MessageResult $context) use ($contextStub, $expectedMessage) { + $this->assertSame($contextStub, $context->getContext()); + $this->assertSame($expectedMessage, $context->getMessage()); + $this->assertInstanceOf(NullLogger::class, $context->getLogger()); + $this->assertSame(Result::ACK, $context->getResult()); }) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); - $queueConsumer->setFallbackSubscriptionConsumer(new DummySubscriptionConsumer()); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); + $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); $queueConsumer->consume(); } - public function testShouldNotCloseContextWhenConsumptionInterruptedByException() + public function testShouldCallOnProcessorExceptionExtensionMethodWithExpectedContext() { - $expectedException = new \Exception(); + $exception = new \LogicException('Exception exception'); + + $expectedMessage = $this->createMessageMock(); $subscriptionConsumerMock = new DummySubscriptionConsumer(); - $subscriptionConsumerMock->addMessage($this->createMessageMock(), 'foo_queue'); + $subscriptionConsumerMock->addMessage($expectedMessage, 'foo_queue'); $consumerStub = $this->createConsumerStub('foo_queue'); $contextStub = $this->createContextStub($consumerStub); - $contextStub - ->expects($this->never()) - ->method('close') - ; - $processorMock = $this->createProcessorMock(); + $processorMock = $this->createProcessorStub(); $processorMock ->expects($this->once()) ->method('process') - ->willThrowException($expectedException) + ->willThrowException($exception) ; - $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1), 0); + $extension = $this->createExtension(); + $extension + ->expects($this->never()) + ->method('onResult') + ; + $extension + ->expects($this->once()) + ->method('onProcessorException') + ->with($this->isInstanceOf(ProcessorException::class)) + ->willReturnCallback(function (ProcessorException $context) use ($contextStub, $expectedMessage, $exception) { + $this->assertSame($contextStub, $context->getContext()); + $this->assertSame($expectedMessage, $context->getMessage()); + $this->assertSame($exception, $context->getException()); + $this->assertGreaterThan(1, $context->getReceivedAt()); + $this->assertInstanceOf(NullLogger::class, $context->getLogger()); + $this->assertNull($context->getResult()); + }) + ; + + $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); - try { - $queueConsumer->consume(); - } catch (\Exception $e) { - $this->assertSame($expectedException, $e); - $this->assertNull($e->getPrevious()); - - return; - } - - $this->fail('Exception throw is expected.'); + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('Exception exception'); + $queueConsumer->consume(); } - public function testShouldSetMainExceptionAsPreviousToExceptionThrownOnInterrupt() + public function testShouldContinueConsumptionIfResultSetOnProcessorExceptionExtension() { - $mainException = new \Exception(); - $expectedException = new \Exception(); + $result = Result::ack(); + + $expectedMessage = $this->createMessageMock(); $subscriptionConsumerMock = new DummySubscriptionConsumer(); - $subscriptionConsumerMock->addMessage($this->createMessageMock(), 'foo_queue'); + $subscriptionConsumerMock->addMessage($expectedMessage, 'foo_queue'); $consumerStub = $this->createConsumerStub('foo_queue'); $contextStub = $this->createContextStub($consumerStub); - $processorMock = $this->createProcessorMock(); + $processorMock = $this->createProcessorStub(); $processorMock ->expects($this->once()) ->method('process') - ->willThrowException($mainException) + ->willThrowException(new \LogicException()) ; $extension = $this->createExtension(); $extension - ->expects($this->atLeastOnce()) - ->method('onInterrupted') - ->willThrowException($expectedException) + ->expects($this->once()) + ->method('onProcessorException') + ->willReturnCallback(function (ProcessorException $context) use ($result) { + $context->setResult($result); + }) + ; + $extension + ->expects($this->once()) + ->method('onResult') + ->willReturnCallback(function (MessageResult $context) use ($result) { + $this->assertSame($result, $context->getResult()); + }) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); - try { - $queueConsumer->consume(); - } catch (\Exception $e) { - $this->assertSame($expectedException, $e); - $this->assertSame($mainException, $e->getPrevious()); - - return; - } - - $this->fail('Exception throw is expected.'); + $queueConsumer->consume(); } - public function testShouldAllowInterruptConsumingOnPreReceiveButProcessCurrentMessage() + public function testShouldCallOnPostMessageReceivedExtensionMethodWithExpectedContext() { $expectedMessage = $this->createMessageMock(); @@ -920,57 +1010,77 @@ public function testShouldAllowInterruptConsumingOnPreReceiveButProcessCurrentMe $contextStub = $this->createContextStub($consumerStub); - $processorMock = $this->createProcessorMock(); - $processorMock - ->expects($this->once()) - ->method('process') - ->willReturn(Result::ACK) - ; + $processorMock = $this->createProcessorStub(); $extension = $this->createExtension(); $extension ->expects($this->once()) - ->method('onPreReceived') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) { - $context->setExecutionInterrupted(true); - }) - ; - $extension - ->expects($this->atLeastOnce()) - ->method('onInterrupted') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ( + ->method('onPostMessageReceived') + ->with($this->isInstanceOf(PostMessageReceived::class)) + ->willReturnCallback(function (PostMessageReceived $context) use ( $contextStub, - $consumerStub, - $processorMock, $expectedMessage ) { - $this->assertSame($contextStub, $context->getInteropContext()); - $this->assertSame($consumerStub, $context->getConsumer()); - $this->assertSame($processorMock, $context->getProcessor()); - $this->assertSame($expectedMessage, $context->getInteropMessage()); + $this->assertSame($contextStub, $context->getContext()); + $this->assertSame($expectedMessage, $context->getMessage()); $this->assertInstanceOf(NullLogger::class, $context->getLogger()); - $this->assertNull($context->getException()); $this->assertSame(Result::ACK, $context->getResult()); - $this->assertTrue($context->isExecutionInterrupted()); + $this->assertFalse($context->isExecutionInterrupted()); }) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); $queueConsumer->consume(); } - public function testShouldAllowInterruptConsumingOnResult() + public function testShouldAllowInterruptConsumingOnPostConsume() { - $expectedMessage = $this->createMessageMock(); + $consumerStub = $this->createConsumerStub('foo_queue'); + + $contextStub = $this->createContextStub($consumerStub); + + $processorMock = $this->createProcessorMock(); + + $extension = $this->createExtension(); + $extension + ->expects($this->once()) + ->method('onPostConsume') + ->with($this->isInstanceOf(PostConsume::class)) + ->willReturnCallback(function (PostConsume $context) { + $context->interruptExecution(); + }) + ; + $extension + ->expects($this->once()) + ->method('onEnd') + ->with($this->isInstanceOf(End::class)) + ->willReturnCallback(function (End $context) use ($contextStub) { + $this->assertSame($contextStub, $context->getContext()); + $this->assertInstanceOf(NullLogger::class, $context->getLogger()); + $this->assertGreaterThan(1, $context->getStartTime()); + $this->assertGreaterThan(1, $context->getEndTime()); + }) + ; + + $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); + $queueConsumer->setFallbackSubscriptionConsumer(new DummySubscriptionConsumer()); + $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); + + $queueConsumer->consume(); + } + + public function testShouldSetMainExceptionAsPreviousToExceptionThrownOnProcessorException() + { + $mainException = new \Exception(); + $expectedException = new \Exception(); $subscriptionConsumerMock = new DummySubscriptionConsumer(); - $subscriptionConsumerMock->addMessage($expectedMessage, 'foo_queue'); + $subscriptionConsumerMock->addMessage($this->createMessageMock(), 'foo_queue'); $consumerStub = $this->createConsumerStub('foo_queue'); @@ -980,48 +1090,34 @@ public function testShouldAllowInterruptConsumingOnResult() $processorMock ->expects($this->once()) ->method('process') - ->willReturn(Result::ACK) + ->willThrowException($mainException) ; $extension = $this->createExtension(); - $extension - ->expects($this->once()) - ->method('onResult') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) { - $context->setExecutionInterrupted(true); - }) - ; $extension ->expects($this->atLeastOnce()) - ->method('onInterrupted') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ( - $contextStub, - $consumerStub, - $processorMock, - $expectedMessage - ) { - $this->assertSame($contextStub, $context->getInteropContext()); - $this->assertSame($consumerStub, $context->getConsumer()); - $this->assertSame($processorMock, $context->getProcessor()); - $this->assertSame($expectedMessage, $context->getInteropMessage()); - $this->assertInstanceOf(NullLogger::class, $context->getLogger()); - $this->assertNull($context->getException()); - $this->assertSame(Result::ACK, $context->getResult()); - $this->assertTrue($context->isExecutionInterrupted()); - }) + ->method('onProcessorException') + ->willThrowException($expectedException) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); - $queueConsumer->consume(); + try { + $queueConsumer->consume(); + } catch (\Exception $e) { + $this->assertSame($expectedException, $e); + $this->assertSame($mainException, $e->getPrevious()); + + return; + } + + $this->fail('Exception throw is expected.'); } - public function testShouldAllowInterruptConsumingOnPostReceive() + public function testShouldAllowInterruptConsumingOnPostMessageReceived() { $expectedMessage = $this->createMessageMock(); @@ -1042,42 +1138,27 @@ public function testShouldAllowInterruptConsumingOnPostReceive() $extension = $this->createExtension(); $extension ->expects($this->once()) - ->method('onPostReceived') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) { - $context->setExecutionInterrupted(true); + ->method('onPostMessageReceived') + ->with($this->isInstanceOf(PostMessageReceived::class)) + ->willReturnCallback(function (PostMessageReceived $context) { + $context->interruptExecution(); }) ; $extension ->expects($this->atLeastOnce()) - ->method('onInterrupted') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ( - $contextStub, - $consumerStub, - $processorMock, - $expectedMessage - ) { - $this->assertSame($contextStub, $context->getInteropContext()); - $this->assertSame($consumerStub, $context->getConsumer()); - $this->assertSame($processorMock, $context->getProcessor()); - $this->assertSame($expectedMessage, $context->getInteropMessage()); - $this->assertInstanceOf(NullLogger::class, $context->getLogger()); - $this->assertNull($context->getException()); - $this->assertSame(Result::ACK, $context->getResult()); - $this->assertTrue($context->isExecutionInterrupted()); - }) + ->method('onEnd') + ->with($this->isInstanceOf(End::class)) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); $queueConsumer->consume(); } - public function testShouldCallOnInterruptedIfExceptionThrow() + public function testShouldNotCallOnEndIfExceptionThrow() { $expectedException = new \Exception('Process failed'); $expectedMessage = $this->createMessageMock(); @@ -1098,29 +1179,12 @@ public function testShouldCallOnInterruptedIfExceptionThrow() $extension = $this->createExtension(); $extension - ->expects($this->atLeastOnce()) - ->method('onInterrupted') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ( - $contextStub, - $consumerStub, - $processorMock, - $expectedMessage, - $expectedException - ) { - $this->assertSame($contextStub, $context->getInteropContext()); - $this->assertSame($consumerStub, $context->getConsumer()); - $this->assertSame($processorMock, $context->getProcessor()); - $this->assertSame($expectedMessage, $context->getInteropMessage()); - $this->assertSame($expectedException, $context->getException()); - $this->assertInstanceOf(NullLogger::class, $context->getLogger()); - $this->assertNull($context->getResult()); - $this->assertTrue($context->isExecutionInterrupted()); - }) + ->expects($this->never()) + ->method('onEnd') ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); @@ -1151,30 +1215,35 @@ public function testShouldCallExtensionPassedOnRuntime() $runtimeExtension ->expects($this->once()) ->method('onStart') - ->with($this->isInstanceOf(Context::class)) + ->with($this->isInstanceOf(Start::class)) ; $runtimeExtension ->expects($this->once()) - ->method('onBeforeReceive') - ->with($this->isInstanceOf(Context::class)) + ->method('onPreSubscribe') + ->with($this->isInstanceOf(PreSubscribe::class)) ; $runtimeExtension ->expects($this->once()) - ->method('onPreReceived') - ->with($this->isInstanceOf(Context::class)) + ->method('onPreConsume') + ->with($this->isInstanceOf(PreConsume::class)) + ; + $runtimeExtension + ->expects($this->once()) + ->method('onMessageReceived') + ->with($this->isInstanceOf(MessageReceived::class)) ; $runtimeExtension ->expects($this->once()) ->method('onResult') - ->with($this->isInstanceOf(Context::class)) + ->with($this->isInstanceOf(MessageResult::class)) ; $runtimeExtension ->expects($this->once()) - ->method('onPostReceived') - ->with($this->isInstanceOf(Context::class)) + ->method('onPostMessageReceived') + ->with($this->isInstanceOf(PostMessageReceived::class)) ; - $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1), 0); + $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(1)); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); @@ -1205,31 +1274,39 @@ public function testShouldChangeLoggerOnStart() $extension ->expects($this->atLeastOnce()) ->method('onStart') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ($expectedLogger) { - $context->setLogger($expectedLogger); + ->with($this->isInstanceOf(Start::class)) + ->willReturnCallback(function (Start $context) use ($expectedLogger) { + $context->changeLogger($expectedLogger); }) ; $extension ->expects($this->atLeastOnce()) - ->method('onBeforeReceive') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ($expectedLogger) { + ->method('onPreSubscribe') + ->with($this->isInstanceOf(PreSubscribe::class)) + ->willReturnCallback(function (PreSubscribe $context) use ($expectedLogger) { $this->assertSame($expectedLogger, $context->getLogger()); }) ; $extension ->expects($this->atLeastOnce()) - ->method('onPreReceived') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use ($expectedLogger) { + ->method('onPreConsume') + ->with($this->isInstanceOf(PreConsume::class)) + ->willReturnCallback(function (PreConsume $context) use ($expectedLogger) { + $this->assertSame($expectedLogger, $context->getLogger()); + }) + ; + $extension + ->expects($this->atLeastOnce()) + ->method('onMessageReceived') + ->with($this->isInstanceOf(MessageReceived::class)) + ->willReturnCallback(function (MessageReceived $context) use ($expectedLogger) { $this->assertSame($expectedLogger, $context->getLogger()); }) ; $chainExtensions = new ChainExtension([$extension, new BreakCycleExtension(1)]); - $queueConsumer = new QueueConsumer($contextStub, $chainExtensions, 0); + $queueConsumer = new QueueConsumer($contextStub, $chainExtensions); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer->bind(new NullQueue('foo_queue'), $processorMock); @@ -1277,20 +1354,20 @@ public function testShouldCallProcessorAsMessageComeAlong() $processorMock = $this->createProcessorStub(); $anotherProcessorMock = $this->createProcessorStub(); - /** @var Context[] $actualContexts */ + /** @var MessageReceived[] $actualContexts */ $actualContexts = []; $extension = $this->createExtension(); $extension ->expects($this->any()) - ->method('onPreReceived') - ->with($this->isInstanceOf(Context::class)) - ->willReturnCallback(function (Context $context) use (&$actualContexts) { + ->method('onMessageReceived') + ->with($this->isInstanceOf(MessageReceived::class)) + ->willReturnCallback(function (MessageReceived $context) use (&$actualContexts) { $actualContexts[] = clone $context; }) ; - $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(3), 0); + $queueConsumer = new QueueConsumer($contextStub, new BreakCycleExtension(3)); $queueConsumer->setFallbackSubscriptionConsumer($subscriptionConsumerMock); $queueConsumer ->bind($queue1, $processorMock) @@ -1301,9 +1378,9 @@ public function testShouldCallProcessorAsMessageComeAlong() $this->assertCount(3, $actualContexts); - $this->assertSame($firstMessage, $actualContexts[0]->getInteropMessage()); - $this->assertSame($secondMessage, $actualContexts[1]->getInteropMessage()); - $this->assertSame($thirdMessage, $actualContexts[2]->getInteropMessage()); + $this->assertSame($firstMessage, $actualContexts[0]->getMessage()); + $this->assertSame($secondMessage, $actualContexts[1]->getMessage()); + $this->assertSame($thirdMessage, $actualContexts[2]->getMessage()); $this->assertSame($fooConsumerStub, $actualContexts[0]->getConsumer()); $this->assertSame($barConsumerStub, $actualContexts[1]->getConsumer()); @@ -1346,11 +1423,6 @@ private function createContextStub(Consumer $consumer = null): InteropContext }) ; - $context - ->expects($this->any()) - ->method('close') - ; - return $context; } diff --git a/pkg/enqueue/Tests/Symfony/Client/ConsumeCommandTest.php b/pkg/enqueue/Tests/Symfony/Client/ConsumeCommandTest.php index 54e15edbd..e57696a02 100644 --- a/pkg/enqueue/Tests/Symfony/Client/ConsumeCommandTest.php +++ b/pkg/enqueue/Tests/Symfony/Client/ConsumeCommandTest.php @@ -12,12 +12,26 @@ use Enqueue\Container\Container; use Enqueue\Null\NullQueue; use Enqueue\Symfony\Client\ConsumeCommand; +use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Tester\CommandTester; class ConsumeCommandTest extends TestCase { + use ClassExtensionTrait; + + public function testShouldBeSubClassOfCommand() + { + $this->assertClassExtends(Command::class, ConsumeCommand::class); + } + + public function testShouldNotBeFinal() + { + $this->assertClassNotFinal(ConsumeCommand::class); + } + public function testCouldBeConstructedWithRequiredAttributes() { new ConsumeCommand($this->createMock(ContainerInterface::class)); @@ -36,11 +50,10 @@ public function testShouldHaveExpectedOptions() $options = $command->getDefinition()->getOptions(); - $this->assertCount(10, $options); + $this->assertCount(9, $options); $this->assertArrayHasKey('memory-limit', $options); $this->assertArrayHasKey('message-limit', $options); $this->assertArrayHasKey('time-limit', $options); - $this->assertArrayHasKey('idle-time', $options); $this->assertArrayHasKey('receive-timeout', $options); $this->assertArrayHasKey('niceness', $options); $this->assertArrayHasKey('client', $options); diff --git a/pkg/enqueue/Tests/Symfony/Client/ProduceCommandTest.php b/pkg/enqueue/Tests/Symfony/Client/ProduceCommandTest.php index 51756b48a..321b4eebd 100644 --- a/pkg/enqueue/Tests/Symfony/Client/ProduceCommandTest.php +++ b/pkg/enqueue/Tests/Symfony/Client/ProduceCommandTest.php @@ -5,12 +5,26 @@ use Enqueue\Client\ProducerInterface; use Enqueue\Container\Container; use Enqueue\Symfony\Client\ProduceCommand; +use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Tester\CommandTester; class ProduceCommandTest extends TestCase { + use ClassExtensionTrait; + + public function testShouldBeSubClassOfCommand() + { + $this->assertClassExtends(Command::class, ProduceCommand::class); + } + + public function testShouldNotBeFinal() + { + $this->assertClassNotFinal(ProduceCommand::class); + } + public function testCouldBeConstructedWithContainerAsFirstArgument() { new ProduceCommand($this->createMock(ContainerInterface::class)); diff --git a/pkg/enqueue/Tests/Symfony/Client/RoutesCommandTest.php b/pkg/enqueue/Tests/Symfony/Client/RoutesCommandTest.php index 4f518848d..daab37e1c 100644 --- a/pkg/enqueue/Tests/Symfony/Client/RoutesCommandTest.php +++ b/pkg/enqueue/Tests/Symfony/Client/RoutesCommandTest.php @@ -23,9 +23,9 @@ public function testShouldBeSubClassOfCommand() $this->assertClassExtends(Command::class, RoutesCommand::class); } - public function testShouldBeFinal() + public function testShouldNotBeFinal() { - $this->assertClassFinal(RoutesCommand::class); + $this->assertClassNotFinal(RoutesCommand::class); } public function testCouldBeConstructedWithConfigAndRouteCollectionAsArguments() diff --git a/pkg/enqueue/Tests/Symfony/Client/SetupBrokerCommandTest.php b/pkg/enqueue/Tests/Symfony/Client/SetupBrokerCommandTest.php index 65ee3063f..b81daf2b3 100644 --- a/pkg/enqueue/Tests/Symfony/Client/SetupBrokerCommandTest.php +++ b/pkg/enqueue/Tests/Symfony/Client/SetupBrokerCommandTest.php @@ -5,12 +5,26 @@ use Enqueue\Client\DriverInterface; use Enqueue\Container\Container; use Enqueue\Symfony\Client\SetupBrokerCommand; +use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Tester\CommandTester; class SetupBrokerCommandTest extends TestCase { + use ClassExtensionTrait; + + public function testShouldBeSubClassOfCommand() + { + $this->assertClassExtends(Command::class, SetupBrokerCommand::class); + } + + public function testShouldNotBeFinal() + { + $this->assertClassNotFinal(SetupBrokerCommand::class); + } + public function testCouldBeConstructedWithContainerAsFirstArgument() { new SetupBrokerCommand($this->createMock(ContainerInterface::class)); diff --git a/pkg/enqueue/Tests/Symfony/Consumption/ConfigurableConsumeCommandTest.php b/pkg/enqueue/Tests/Symfony/Consumption/ConfigurableConsumeCommandTest.php index ef50ad228..b402960ac 100644 --- a/pkg/enqueue/Tests/Symfony/Consumption/ConfigurableConsumeCommandTest.php +++ b/pkg/enqueue/Tests/Symfony/Consumption/ConfigurableConsumeCommandTest.php @@ -8,16 +8,30 @@ use Enqueue\Consumption\QueueSubscriberInterface; use Enqueue\Container\Container; use Enqueue\Symfony\Consumption\ConfigurableConsumeCommand; +use Enqueue\Test\ClassExtensionTrait; use Interop\Queue\Context; use Interop\Queue\Message as InteropMessage; use Interop\Queue\Processor; use Interop\Queue\Queue as InteropQueue; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Tester\CommandTester; class ConfigurableConsumeCommandTest extends TestCase { + use ClassExtensionTrait; + + public function testShouldBeSubClassOfCommand() + { + $this->assertClassExtends(Command::class, ConfigurableConsumeCommand::class); + } + + public function testShouldNotBeFinal() + { + $this->assertClassNotFinal(ConfigurableConsumeCommand::class); + } + public function testCouldBeConstructedWithRequiredAttributes() { new ConfigurableConsumeCommand($this->createMock(ContainerInterface::class)); @@ -36,11 +50,10 @@ public function testShouldHaveExpectedOptions() $options = $command->getDefinition()->getOptions(); - $this->assertCount(8, $options); + $this->assertCount(7, $options); $this->assertArrayHasKey('memory-limit', $options); $this->assertArrayHasKey('message-limit', $options); $this->assertArrayHasKey('time-limit', $options); - $this->assertArrayHasKey('idle-time', $options); $this->assertArrayHasKey('receive-timeout', $options); $this->assertArrayHasKey('niceness', $options); $this->assertArrayHasKey('transport', $options); diff --git a/pkg/enqueue/Tests/Symfony/Consumption/ConsumeCommandTest.php b/pkg/enqueue/Tests/Symfony/Consumption/ConsumeCommandTest.php index 70bc57251..a8ead2d8e 100644 --- a/pkg/enqueue/Tests/Symfony/Consumption/ConsumeCommandTest.php +++ b/pkg/enqueue/Tests/Symfony/Consumption/ConsumeCommandTest.php @@ -6,12 +6,26 @@ use Enqueue\Consumption\QueueConsumerInterface; use Enqueue\Container\Container; use Enqueue\Symfony\Consumption\ConsumeCommand; +use Enqueue\Test\ClassExtensionTrait; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Tester\CommandTester; class ConsumeCommandTest extends TestCase { + use ClassExtensionTrait; + + public function testShouldBeSubClassOfCommand() + { + $this->assertClassExtends(Command::class, ConsumeCommand::class); + } + + public function testShouldNotBeFinal() + { + $this->assertClassNotFinal(ConsumeCommand::class); + } + public function testCouldBeConstructedWithRequiredAttributes() { new ConsumeCommand($this->createMock(ContainerInterface::class)); @@ -30,11 +44,10 @@ public function testShouldHaveExpectedOptions() $options = $command->getDefinition()->getOptions(); - $this->assertCount(8, $options); + $this->assertCount(7, $options); $this->assertArrayHasKey('memory-limit', $options); $this->assertArrayHasKey('message-limit', $options); $this->assertArrayHasKey('time-limit', $options); - $this->assertArrayHasKey('idle-time', $options); $this->assertArrayHasKey('receive-timeout', $options); $this->assertArrayHasKey('niceness', $options); $this->assertArrayHasKey('transport', $options); diff --git a/pkg/enqueue/Tests/Symfony/Consumption/QueueConsumerOptionsCommandTraitTest.php b/pkg/enqueue/Tests/Symfony/Consumption/QueueConsumerOptionsCommandTraitTest.php index 74791725d..c221f0284 100644 --- a/pkg/enqueue/Tests/Symfony/Consumption/QueueConsumerOptionsCommandTraitTest.php +++ b/pkg/enqueue/Tests/Symfony/Consumption/QueueConsumerOptionsCommandTraitTest.php @@ -15,31 +15,24 @@ public function testShouldAddExtensionsOptions() $options = $trait->getDefinition()->getOptions(); - $this->assertCount(2, $options); - $this->assertArrayHasKey('idle-time', $options); + $this->assertCount(1, $options); $this->assertArrayHasKey('receive-timeout', $options); } public function testShouldSetQueueConsumerOptions() { $consumer = $this->createQueueConsumer(); - $consumer - ->expects($this->once()) - ->method('setIdleTimeout') - ->with($this->identicalTo(123.1)) - ; $consumer ->expects($this->once()) ->method('setReceiveTimeout') - ->with($this->identicalTo(456.1)) + ->with($this->identicalTo(456)) ; $trait = new QueueConsumerOptionsCommand($consumer); $tester = new CommandTester($trait); $tester->execute([ - '--idle-time' => '123.1', - '--receive-timeout' => '456.1', + '--receive-timeout' => '456', ]); } diff --git a/pkg/enqueue/Tests/Symfony/DependencyInjection/TransportFactoryTest.php b/pkg/enqueue/Tests/Symfony/DependencyInjection/TransportFactoryTest.php index 993c2b365..5da72c759 100644 --- a/pkg/enqueue/Tests/Symfony/DependencyInjection/TransportFactoryTest.php +++ b/pkg/enqueue/Tests/Symfony/DependencyInjection/TransportFactoryTest.php @@ -376,7 +376,6 @@ public function testShouldBuildQueueConsumerWithDefaultOptions() $transport->buildQueueConsumer($container, []); - $this->assertSame(0, $container->getParameter('enqueue.transport.default.idle_time')); $this->assertSame(10000, $container->getParameter('enqueue.transport.default.receive_timeout')); $this->assertTrue($container->hasDefinition('enqueue.transport.default.consumption_extensions')); @@ -388,7 +387,8 @@ public function testShouldBuildQueueConsumerWithDefaultOptions() $this->assertEquals([ new Reference('enqueue.transport.default.context'), new Reference('enqueue.transport.default.consumption_extensions'), - '%enqueue.transport.default.idle_time%', + [], + null, '%enqueue.transport.default.receive_timeout%', ], $container->getDefinition('enqueue.transport.default.queue_consumer')->getArguments()); } @@ -401,11 +401,9 @@ public function testShouldBuildQueueConsumerWithCustomOptions() $transport = new TransportFactory('default'); $transport->buildQueueConsumer($container, [ - 'idle_time' => 123, 'receive_timeout' => 567, ]); - $this->assertSame(123, $container->getParameter('enqueue.transport.default.idle_time')); $this->assertSame(567, $container->getParameter('enqueue.transport.default.receive_timeout')); } diff --git a/pkg/test/ClassExtensionTrait.php b/pkg/test/ClassExtensionTrait.php index e2bd84069..75d70ae63 100644 --- a/pkg/test/ClassExtensionTrait.php +++ b/pkg/test/ClassExtensionTrait.php @@ -33,4 +33,14 @@ public function assertClassFinal($actual) sprintf('Failed assert that class %s is final.', $actual) ); } + + public function assertClassNotFinal($actual) + { + $rc = new \ReflectionClass($actual); + + $this->assertFalse( + $rc->isFinal(), + sprintf('Failed assert that class %s is final.', $actual) + ); + } }