From 027dfe84692c310d221891373a6dc46e22c575f4 Mon Sep 17 00:00:00 2001 From: abublihi Date: Mon, 8 Apr 2024 05:06:05 +0300 Subject: [PATCH 1/5] Add support for laravel octane, by keeping the resolved Producer and Consumer service container will keep the connection active for all requests coming to the same worker --- readme.md | 13 +++++++++++++ src/Amqp.php | 8 ++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 83e199f..355060d 100644 --- a/readme.md +++ b/readme.md @@ -83,6 +83,19 @@ name. - `amqp.connections.*.consumer` holds the default properties of consumer when consuming. - `amqp.connections.*.qos` holds the default properties of QoS when consuming. +### Octane support + +From >=2.1 this package supports laravel octane by default, but you have to configure octane to `warm` the connection, by adding 'amqp' to the warm array in octane configurations. + +```php + // config\octane.php + // ... + 'warm' => [ + // ... + 'amqp', // <-- this line + ], +``` + ## Usage The followings work the same. diff --git a/src/Amqp.php b/src/Amqp.php index c49213e..43781a1 100644 --- a/src/Amqp.php +++ b/src/Amqp.php @@ -20,6 +20,10 @@ class Amqp implements AmqpPubSub private $config; + private Producer $producer; + + private Consumer $consumer; + public function __construct(AbstractConnection $connection, array $config = []) { $this->connection = $connection; @@ -28,12 +32,12 @@ public function __construct(AbstractConnection $connection, array $config = []) public function getProducer(): Producer { - return app()->make(Producer::class, ['connection' => $this->connection]); + return $this->producer ?? $this->producer = app()->make(Producer::class, ['connection' => $this->connection]); } public function getConsumer(array $options = []): Consumer { - return app()->make( + return $this->consumer ?? $this->consumer = app()->make( Consumer::class, ['connection' => $this->connection, 'channel' => null, 'options' => $options] ); From bf71584659b74e613612af40abe719a945724983 Mon Sep 17 00:00:00 2001 From: Syed Sirajul Islam Anik Date: Sat, 20 Apr 2024 05:48:39 +0600 Subject: [PATCH 2/5] readme update --- readme.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/readme.md b/readme.md index 15a0f75..f319a05 100644 --- a/readme.md +++ b/readme.md @@ -86,15 +86,17 @@ name. ### Octane support -From >=2.1 this package supports laravel octane by default, but you have to configure octane to `warm` the connection, by adding 'amqp' to the warm array in octane configurations. +This package supports laravel octane by +default. [To keep the AMQP connection alive](https://www.cloudamqp.com/blog/part4-rabbitmq-13-common-errors.html), +you have to configure octane to `warm` the connection, by adding **'amqp'** to the warm array in octane configurations. ```php - // config\octane.php - // ... - 'warm' => [ - // ... - 'amqp', // <-- this line - ], +// config/octane.php +// ... +'warm' => [ + // ... + 'amqp', // <-- this line +], ``` ## Usage @@ -287,6 +289,7 @@ class MyTest extends TestCase - If a message exactly matches the `$message`. - If a message exactly matches the `get_class($message)`. - If a message is an implementation of `$message`. + ### Note Using `Anik\Laravel\Amqp\Facades\Amqp::consume()` after `Anik\Laravel\Amqp\Facades\Amqp::fake()` will throw exception. From 7b2b9d1b24c1d7e597c2f9a2846024701ee0655e Mon Sep 17 00:00:00 2001 From: Syed Sirajul Islam Anik Date: Sat, 20 Apr 2024 05:49:50 +0600 Subject: [PATCH 3/5] reverted the consumer connection property --- src/Amqp.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Amqp.php b/src/Amqp.php index 43781a1..0e17311 100644 --- a/src/Amqp.php +++ b/src/Amqp.php @@ -22,8 +22,6 @@ class Amqp implements AmqpPubSub private Producer $producer; - private Consumer $consumer; - public function __construct(AbstractConnection $connection, array $config = []) { $this->connection = $connection; @@ -32,12 +30,12 @@ public function __construct(AbstractConnection $connection, array $config = []) public function getProducer(): Producer { - return $this->producer ?? $this->producer = app()->make(Producer::class, ['connection' => $this->connection]); + return $this->producer ??= app()->make(Producer::class, ['connection' => $this->connection]); } public function getConsumer(array $options = []): Consumer { - return $this->consumer ?? $this->consumer = app()->make( + return app()->make( Consumer::class, ['connection' => $this->connection, 'channel' => null, 'options' => $options] ); From fd263e98aafc3a4d4d57ea6bc0938dac10404f24 Mon Sep 17 00:00:00 2001 From: Syed Sirajul Islam Anik Date: Sat, 20 Apr 2024 06:07:11 +0600 Subject: [PATCH 4/5] indentation fix --- tests/AmqpTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/AmqpTest.php b/tests/AmqpTest.php index bd78958..208fe6e 100644 --- a/tests/AmqpTest.php +++ b/tests/AmqpTest.php @@ -347,7 +347,7 @@ public static function consumerConfigTestDataProvider(): array /** * @dataProvider publishMessageTestDataProvider * - * @param array $data + * @param array $data */ public function testPublishFormatsMessagesToProducible(array $data) { @@ -432,7 +432,7 @@ public function testPublishPassesExpectedRoutingKey() /** * @dataProvider publishOptionsDataProvider * - * @param array $data + * @param array $data */ public function testPublishPassesPublishOptionsIfAvailable(array $data) { @@ -471,7 +471,7 @@ function ($options) use ($expectations) { /** * @dataProvider exchangeTestDataProvider * - * @param array $data + * @param array $data */ public function testPublishMessageProcessesExchange(array $data) { @@ -563,7 +563,7 @@ function () { /** * @dataProvider exchangeTestDataProvider * - * @param array $data + * @param array $data */ public function testConsumerProcessesExchange(array $data) { @@ -611,7 +611,7 @@ function () { /** * @dataProvider queueTestDataProvider * - * @param array $data + * @param array $data */ public function testConsumerProcessesQueue(array $data) { @@ -659,7 +659,7 @@ function () { /** * @dataProvider qosTestDataProvider * - * @param array $data + * @param array $data */ public function testConsumerProcessesQos(array $data) { @@ -714,7 +714,7 @@ function () { /** * @dataProvider queueBindTestDataProvider * - * @param array $data + * @param array $data */ public function testConsumerProcessesQueueBind(array $data) { @@ -762,7 +762,7 @@ function () { /** * @dataProvider consumerConfigTestDataProvider * - * @param array $data + * @param array $data */ public function testConsumerProcessesConsumerConfig(array $data) { From 823191c1c09c3d914b8cecda2b61433b83a06448 Mon Sep 17 00:00:00 2001 From: Syed Sirajul Islam Anik Date: Sat, 20 Apr 2024 06:07:28 +0600 Subject: [PATCH 5/5] testcase added for producer reusability --- tests/AmqpTest.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/AmqpTest.php b/tests/AmqpTest.php index 208fe6e..167022e 100644 --- a/tests/AmqpTest.php +++ b/tests/AmqpTest.php @@ -511,6 +511,33 @@ function ($options) use ($expectation) { ); } + public function testReusesResolvedProducer() + { + $this->bindProducerToApp($producer = $this->getProducerMock($this->connection)); + + $producer->expects($this->exactly(2))->method('publishBatch'); + + $amqp = $this->getAmqpInstance(null, ['exchange' => ['name' => self::EXCHANGE_NAME, 'type' => 'topic']]); + $amqp->publish( + 'my message', + 'my-binding-key', + $data['exchange'] ?? null, + $data['options'] ?? [] + ); + + // Bind new producer to the container + $this->bindProducerToApp($producer2 = $this->getProducerMock($this->connection)); + // This producer should never be called as the previous producer is already stored in the class. + $producer2->expects($this->never())->method('publishBatch'); + + $amqp->publish( + 'my another message', + 'my-binding-key', + $data['exchange'] ?? null, + $data['options'] ?? [] + ); + } + public function testConsumeHandlerIsChangesCallableToConsumable() { $this->bindConsumerToApp($consumer = $this->getConsumerMock($this->connection));