From 033cf7b34d5ea27688e258dab795e60f0de0636a Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 14 May 2019 16:03:21 +0300 Subject: [PATCH 1/6] [client] Lazy producer. --- composer.json | 24 ++-- .../Functional/App/config/custom-config.yml | 4 + .../Tests/Functional/LazyProducerTest.php | 79 +++++++++++ .../Tests/Functional/UseCasesTest.php | 6 +- .../Tests/Functional/WebTestCase.php | 4 +- .../DependencyInjection/ClientFactory.php | 15 +- pkg/enqueue/Symfony/Client/LazyProducer.php | 37 +++++ .../BuildProcessorRegistryPassTest.php | 4 +- .../BuildProcessorRegistryPassTest.php | 4 +- .../Tests/Symfony/LazyProducerTest.php | 133 ++++++++++++++++++ 10 files changed, 286 insertions(+), 24 deletions(-) create mode 100644 pkg/enqueue-bundle/Tests/Functional/LazyProducerTest.php create mode 100644 pkg/enqueue/Symfony/Client/LazyProducer.php create mode 100644 pkg/enqueue/Tests/Symfony/LazyProducerTest.php diff --git a/composer.json b/composer.json index 639b274b6..4dbb1423d 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,6 @@ "ramsey/uuid": "^2|^3.5", "psr/log": "^1", "psr/container": "^1", - "symfony/event-dispatcher": "4.0.*", "makasim/temp-file": "^0.2", "google/cloud-pubsub": "^0.6.1|^1.0", "doctrine/orm": "~2.4", @@ -40,20 +39,20 @@ "phpunit/phpunit": "^5.5", "phpstan/phpstan": "^0.10", "queue-interop/queue-spec": "^0.6", - "symfony/browser-kit": "4.0.*", - "symfony/config": "4.0.*", - "symfony/process": "4.0.*", - "symfony/console": "4.0.*", - "symfony/dependency-injection": "4.0.*", - "symfony/event-dispatcher": "4.0.*", - "symfony/expression-language": "4.0.*", - "symfony/http-kernel": "4.0.*", - "symfony/filesystem": "4.0.*", - "symfony/framework-bundle": "4.0.*", + "symfony/browser-kit": "^4", + "symfony/config": "^4", + "symfony/process": "^4", + "symfony/console": "^3.4|^4", + "symfony/dependency-injection": "^4", + "symfony/event-dispatcher": "^3.4|^4", + "symfony/expression-language": "^4", + "symfony/http-kernel": "^4", + "symfony/filesystem": "^4", + "symfony/framework-bundle": "^4", "empi89/php-amqp-stubs": "*@dev", "doctrine/doctrine-bundle": "~1.2", "kwn/php-rdkafka-stubs": "^1.0.2", - "friendsofphp/php-cs-fixer": "^2" + "friendsofphp/php-cs-fixer": "^2.15" }, "autoload": { "psr-4": { @@ -103,6 +102,7 @@ "config": { "bin-dir": "bin", "platform": { + "php": "7.3", "ext-amqp": "1.9.3", "ext-gearman": "2.0.3", "ext-rdkafka": "3.3", diff --git a/pkg/enqueue-bundle/Tests/Functional/App/config/custom-config.yml b/pkg/enqueue-bundle/Tests/Functional/App/config/custom-config.yml index eab956cc4..eda14e00c 100644 --- a/pkg/enqueue-bundle/Tests/Functional/App/config/custom-config.yml +++ b/pkg/enqueue-bundle/Tests/Functional/App/config/custom-config.yml @@ -31,6 +31,10 @@ services: alias: 'enqueue.client.default.producer' public: true + test_enqueue.client.default.lazy_producer: + alias: 'enqueue.client.default.lazy_producer' + public: true + test_enqueue.transport.default.context: alias: 'enqueue.transport.default.context' public: true diff --git a/pkg/enqueue-bundle/Tests/Functional/LazyProducerTest.php b/pkg/enqueue-bundle/Tests/Functional/LazyProducerTest.php new file mode 100644 index 000000000..cf9af030e --- /dev/null +++ b/pkg/enqueue-bundle/Tests/Functional/LazyProducerTest.php @@ -0,0 +1,79 @@ +remove(static::$kernel->getLogDir()); + $fs->remove(static::$kernel->getCacheDir()); + } + + parent::tearDown(); + } + + public function testShouldAllowGetLazyProducerWithoutError() + { + $this->customSetUp([ + 'default' => [ + 'transport' => [ + 'dsn' => 'invalidDSN', + ], + ], + ]); + + /** @var LazyProducer $producer */ + $producer = static::$container->get('test_enqueue.client.default.lazy_producer'); + $this->assertInstanceOf(LazyProducer::class, $producer); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('The DSN is invalid.'); + $producer->sendEvent('foo', 'foo'); + } + + /** + * @return string + */ + public static function getKernelClass() + { + include_once __DIR__.'/App/CustomAppKernel.php'; + + return CustomAppKernel::class; + } + + protected function customSetUp(array $enqueueConfig) + { + static::$class = null; + + static::$client = static::createClient(['enqueue_config' => $enqueueConfig]); + static::$client->getKernel()->boot(); + static::$kernel = static::$client->getKernel(); + static::$container = static::$kernel->getContainer(); + } + + protected static function createKernel(array $options = []): CustomAppKernel + { + /** @var CustomAppKernel $kernel */ + $kernel = parent::createKernel($options); + + $kernel->setEnqueueConfig(isset($options['enqueue_config']) ? $options['enqueue_config'] : []); + + return $kernel; + } +} diff --git a/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php b/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php index 0a5f38325..f4f11abb1 100644 --- a/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php +++ b/pkg/enqueue-bundle/Tests/Functional/UseCasesTest.php @@ -372,9 +372,9 @@ protected function customSetUp(array $enqueueConfig) { static::$class = null; - $this->client = static::createClient(['enqueue_config' => $enqueueConfig]); - $this->client->getKernel()->boot(); - static::$kernel = $this->client->getKernel(); + static::$client = static::createClient(['enqueue_config' => $enqueueConfig]); + static::$client->getKernel()->boot(); + static::$kernel = static::$client->getKernel(); static::$container = static::$kernel->getContainer(); /** @var DriverInterface $driver */ diff --git a/pkg/enqueue-bundle/Tests/Functional/WebTestCase.php b/pkg/enqueue-bundle/Tests/Functional/WebTestCase.php index 0cf1a0723..fa4eb3e5a 100644 --- a/pkg/enqueue-bundle/Tests/Functional/WebTestCase.php +++ b/pkg/enqueue-bundle/Tests/Functional/WebTestCase.php @@ -13,7 +13,7 @@ abstract class WebTestCase extends BaseWebTestCase /** * @var Client */ - protected $client; + protected static $client; /** * @var ContainerInterface @@ -26,7 +26,7 @@ protected function setUp() static::$class = null; - $this->client = static::createClient(); + static::$client = static::createClient(); if (false == static::$container) { static::$container = static::$kernel->getContainer(); diff --git a/pkg/enqueue/Symfony/Client/DependencyInjection/ClientFactory.php b/pkg/enqueue/Symfony/Client/DependencyInjection/ClientFactory.php index e69311e36..bdae6f3b5 100644 --- a/pkg/enqueue/Symfony/Client/DependencyInjection/ClientFactory.php +++ b/pkg/enqueue/Symfony/Client/DependencyInjection/ClientFactory.php @@ -21,12 +21,14 @@ use Enqueue\Consumption\QueueConsumer; use Enqueue\Rpc\RpcFactory; use Enqueue\Symfony\Client\FlushSpoolProducerListener; +use Enqueue\Symfony\Client\LazyProducer; use Enqueue\Symfony\ContainerProcessorRegistry; use Enqueue\Symfony\DependencyInjection\TransportFactory; use Enqueue\Symfony\DiUtils; use Interop\Queue\Context; use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; use Symfony\Component\Config\Definition\Builder\NodeDefinition; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; @@ -119,14 +121,21 @@ public function build(ContainerBuilder $container, array $config): void ; $container->register($this->diUtils->format('producer'), Producer::class) + // @deprecated ->setPublic(true) ->addArgument($this->diUtils->reference('driver')) ->addArgument($this->diUtils->reference('rpc_factory')) ->addArgument($this->diUtils->reference('client_extensions')) ; + $lazyProducer = $container->register($this->diUtils->format('lazy_producer'), LazyProducer::class); + $lazyProducer->addArgument(ServiceLocatorTagPass::register($container, [ + $this->diUtils->format('producer') => new Reference($this->diUtils->format('producer')), + ])); + $lazyProducer->addArgument($this->diUtils->format('producer')); + $container->register($this->diUtils->format('spool_producer'), SpoolProducer::class) - ->addArgument($this->diUtils->reference('producer')) + ->addArgument($this->diUtils->reference('lazy_producer')) ; $container->register($this->diUtils->format('client_extensions'), ChainExtension::class) @@ -200,12 +209,12 @@ public function build(ContainerBuilder $container, array $config): void $this->diUtils->format('queue_consumer') => $this->diUtils->reference('queue_consumer'), $this->diUtils->format('driver') => $this->diUtils->reference('driver'), $this->diUtils->format('delegate_processor') => $this->diUtils->reference('delegate_processor'), - $this->diUtils->format('producer') => $this->diUtils->reference('producer'), + $this->diUtils->format('producer') => $this->diUtils->reference('lazy_producer'), ])); } if ($this->default) { - $container->setAlias(ProducerInterface::class, $this->diUtils->format('producer')); + $container->setAlias(ProducerInterface::class, $this->diUtils->format('lazy_producer')); $container->setAlias(SpoolProducer::class, $this->diUtils->format('spool_producer')); if (DiUtils::DEFAULT_CONFIG !== $this->diUtils->getConfigName()) { diff --git a/pkg/enqueue/Symfony/Client/LazyProducer.php b/pkg/enqueue/Symfony/Client/LazyProducer.php new file mode 100644 index 000000000..8dd3aadba --- /dev/null +++ b/pkg/enqueue/Symfony/Client/LazyProducer.php @@ -0,0 +1,37 @@ +container = $container; + $this->producerId = $producerId; + } + + public function sendEvent(string $topic, $message): void + { + $this->getRealProducer()->sendEvent($topic, $message); + } + + public function sendCommand(string $command, $message, bool $needReply = false): ?Promise + { + return $this->getRealProducer()->sendCommand($command, $message, $needReply); + } + + private function getRealProducer(): ProducerInterface + { + return $this->container->get($this->producerId); + } +} diff --git a/pkg/enqueue/Tests/Symfony/Client/DependencyInjection/BuildProcessorRegistryPassTest.php b/pkg/enqueue/Tests/Symfony/Client/DependencyInjection/BuildProcessorRegistryPassTest.php index c0142f0e3..4d95ca07d 100644 --- a/pkg/enqueue/Tests/Symfony/Client/DependencyInjection/BuildProcessorRegistryPassTest.php +++ b/pkg/enqueue/Tests/Symfony/Client/DependencyInjection/BuildProcessorRegistryPassTest.php @@ -136,10 +136,10 @@ private function assertLocatorServices(ContainerBuilder $container, $locatorId, $locatorId = (string) $locatorId; $this->assertTrue($container->hasDefinition($locatorId)); - $this->assertRegExp('/service_locator\..*?\.enqueue\./', $locatorId); + $this->assertRegExp('/\.?service_locator\..*?\.enqueue\./', $locatorId); $match = []; - if (false == preg_match('/(service_locator\..*?)\.enqueue\./', $locatorId, $match)) { + if (false == preg_match('/(\.?service_locator\..*?)\.enqueue\./', $locatorId, $match)) { $this->fail('preg_match should not failed'); } diff --git a/pkg/enqueue/Tests/Symfony/DependencyInjection/BuildProcessorRegistryPassTest.php b/pkg/enqueue/Tests/Symfony/DependencyInjection/BuildProcessorRegistryPassTest.php index d122e044c..989d048cf 100644 --- a/pkg/enqueue/Tests/Symfony/DependencyInjection/BuildProcessorRegistryPassTest.php +++ b/pkg/enqueue/Tests/Symfony/DependencyInjection/BuildProcessorRegistryPassTest.php @@ -199,10 +199,10 @@ private function assertLocatorServices(ContainerBuilder $container, $locatorId, $locatorId = (string) $locatorId; $this->assertTrue($container->hasDefinition($locatorId)); - $this->assertRegExp('/service_locator\..*?\.enqueue\./', $locatorId); + $this->assertRegExp('/\.?service_locator\..*?\.enqueue\./', $locatorId); $match = []; - if (false == preg_match('/(service_locator\..*?)\.enqueue\./', $locatorId, $match)) { + if (false == preg_match('/(\.?service_locator\..*?)\.enqueue\./', $locatorId, $match)) { $this->fail('preg_match should not failed'); } diff --git a/pkg/enqueue/Tests/Symfony/LazyProducerTest.php b/pkg/enqueue/Tests/Symfony/LazyProducerTest.php new file mode 100644 index 000000000..b574414c7 --- /dev/null +++ b/pkg/enqueue/Tests/Symfony/LazyProducerTest.php @@ -0,0 +1,133 @@ +assertClassImplements(ProducerInterface::class, LazyProducer::class); + } + + public function testCouldBeConstructedWithContainerAndServiceId() + { + new LazyProducer($this->createContainerMock(), 'realProducerId'); + } + + public function testShouldNotCallRealProducerInConstructor() + { + $containerMock = $this->createContainerMock(); + $containerMock + ->expects($this->never()) + ->method('get') + ; + + new LazyProducer($containerMock, 'realProducerId'); + } + + public function testShouldProxyAllArgumentOnSendEvent() + { + $topic = 'theTopic'; + $message = 'theMessage'; + + $realProducerMock = $this->createProducerMock(); + $realProducerMock + ->expects($this->once()) + ->method('sendEvent') + ->with($topic, $message) + ; + + $containerMock = $this->createContainerMock(); + $containerMock + ->expects($this->once()) + ->method('get') + ->with('realProducerId') + ->willReturn($realProducerMock) + ; + + $lazyProducer = new LazyProducer($containerMock, 'realProducerId'); + + $lazyProducer->sendEvent($topic, $message); + } + + public function testShouldProxyAllArgumentOnSendCommand() + { + $command = 'theCommand'; + $message = 'theMessage'; + $needReply = false; + + $realProducerMock = $this->createProducerMock(); + $realProducerMock + ->expects($this->once()) + ->method('sendCommand') + ->with($command, $message, $needReply) + ; + + $containerMock = $this->createContainerMock(); + $containerMock + ->expects($this->once()) + ->method('get') + ->with('realProducerId') + ->willReturn($realProducerMock) + ; + + $lazyProducer = new LazyProducer($containerMock, 'realProducerId'); + + $result = $lazyProducer->sendCommand($command, $message, $needReply); + + $this->assertNull($result); + } + + public function testShouldProxyReturnedPromiseBackOnSendCommand() + { + $expectedPromise = $this->createMock(Promise::class); + + $realProducerMock = $this->createProducerMock(); + $realProducerMock + ->expects($this->once()) + ->method('sendCommand') + ->willReturn($expectedPromise) + ; + + $containerMock = $this->createContainerMock(); + $containerMock + ->expects($this->once()) + ->method('get') + ->with('realProducerId') + ->willReturn($realProducerMock) + ; + + $lazyProducer = new LazyProducer($containerMock, 'realProducerId'); + + $actualPromise = $lazyProducer->sendCommand('aCommand', 'aMessage', true); + + $this->assertSame($expectedPromise, $actualPromise); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|ProducerInterface + */ + private function createProducerMock(): ProducerInterface + { + return $this->createMock(ProducerInterface::class); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|ContainerInterface + */ + private function createContainerMock(): ContainerInterface + { + return $this->createMock(ContainerInterface::class); + } +} From 5920b78a9c275a7c8383b1a398eebe52b4b5866f Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 14 May 2019 16:14:38 +0300 Subject: [PATCH 2/6] remove php from composer platform --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 4dbb1423d..1465ada7b 100644 --- a/composer.json +++ b/composer.json @@ -102,7 +102,6 @@ "config": { "bin-dir": "bin", "platform": { - "php": "7.3", "ext-amqp": "1.9.3", "ext-gearman": "2.0.3", "ext-rdkafka": "3.3", From aaab015fca50dcba5edfd847a7c16bb9e6920d65 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 14 May 2019 16:20:57 +0300 Subject: [PATCH 3/6] upd --- composer.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 1465ada7b..cb9751df8 100644 --- a/composer.json +++ b/composer.json @@ -39,20 +39,20 @@ "phpunit/phpunit": "^5.5", "phpstan/phpstan": "^0.10", "queue-interop/queue-spec": "^0.6", - "symfony/browser-kit": "^4", - "symfony/config": "^4", - "symfony/process": "^4", + "symfony/browser-kit": "^3.4|^4", + "symfony/config": "^3.4|^4", + "symfony/process": "^3.4|^4", "symfony/console": "^3.4|^4", - "symfony/dependency-injection": "^4", + "symfony/dependency-injection": "^3.4|^4", "symfony/event-dispatcher": "^3.4|^4", - "symfony/expression-language": "^4", - "symfony/http-kernel": "^4", - "symfony/filesystem": "^4", - "symfony/framework-bundle": "^4", + "symfony/expression-language": "^3.4|^4", + "symfony/http-kernel": "^3.4|^4", + "symfony/filesystem": "^3.4|^4", + "symfony/framework-bundle": "^3.4|^4", "empi89/php-amqp-stubs": "*@dev", "doctrine/doctrine-bundle": "~1.2", "kwn/php-rdkafka-stubs": "^1.0.2", - "friendsofphp/php-cs-fixer": "^2.15" + "friendsofphp/php-cs-fixer": "^2" }, "autoload": { "psr-4": { From a951b52f273ffc443a019738af9dcf243ba7b3db Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 14 May 2019 16:28:08 +0300 Subject: [PATCH 4/6] run tests on php 7.3 and for symfony 4.1 and 4.2 --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index f358a00cf..ecc11eaf0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,12 @@ matrix: - php: 7.2 sudo: false env: SYMFONY_VERSION=4.0.* UNIT_TESTS=true + - php: 7.3 + sudo: false + env: SYMFONY_VERSION=4.1.* UNIT_TESTS=true + - php: 7.3 + sudo: false + env: SYMFONY_VERSION=4.2.* UNIT_TESTS=true - php: 7.1 services: docker sudo: required From a3848391dd46affe26b1c28df1356d06fa71f5ba Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 14 May 2019 16:44:27 +0300 Subject: [PATCH 5/6] fix test --- pkg/job-queue/Tests/Functional/WebTestCase.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/job-queue/Tests/Functional/WebTestCase.php b/pkg/job-queue/Tests/Functional/WebTestCase.php index 329762004..ecb6e5af9 100644 --- a/pkg/job-queue/Tests/Functional/WebTestCase.php +++ b/pkg/job-queue/Tests/Functional/WebTestCase.php @@ -11,7 +11,7 @@ abstract class WebTestCase extends BaseWebTestCase /** * @var Client */ - protected $client; + protected static $client; /** * @var ContainerInterface @@ -24,7 +24,7 @@ protected function setUp() static::$class = null; - $this->client = static::createClient(); + static::$client = static::createClient(); if (false == static::$container) { static::$container = static::$kernel->getContainer(); From 665891d6ed16022975796b1c3111474d373d93e7 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Tue, 14 May 2019 17:01:51 +0300 Subject: [PATCH 6/6] fix tests --- pkg/enqueue-bundle/Tests/Functional/WebTestCase.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pkg/enqueue-bundle/Tests/Functional/WebTestCase.php b/pkg/enqueue-bundle/Tests/Functional/WebTestCase.php index fa4eb3e5a..2b4f58173 100644 --- a/pkg/enqueue-bundle/Tests/Functional/WebTestCase.php +++ b/pkg/enqueue-bundle/Tests/Functional/WebTestCase.php @@ -25,18 +25,21 @@ protected function setUp() parent::setUp(); static::$class = null; - static::$client = static::createClient(); - - if (false == static::$container) { - static::$container = static::$kernel->getContainer(); - } + static::$container = static::$kernel->getContainer(); /** @var TraceableProducer $producer */ $producer = static::$container->get('test_enqueue.client.default.traceable_producer'); $producer->clearTraces(); } + protected function tearDown() + { + static::$client = null; + static::$kernel = null; + static::$container = null; + } + /** * @return string */