Skip to content

Commit

Permalink
Add support for laravel octane (#12)
Browse files Browse the repository at this point in the history
* 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 update

* reverted the consumer connection property

* indentation fix

* testcase added for producer reusability

---------

Co-authored-by: Syed Sirajul Islam Anik <sirajul.islam.anik@gmail.com>
  • Loading branch information
abublihi and ssi-anik authored Apr 20, 2024
1 parent 1f6ef40 commit d31c0aa
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 9 deletions.
16 changes: 16 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,21 @@ 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

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
],
```

## Usage

The followings work the same.
Expand Down Expand Up @@ -274,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.
4 changes: 3 additions & 1 deletion src/Amqp.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class Amqp implements AmqpPubSub

private $config;

private Producer $producer;

public function __construct(AbstractConnection $connection, array $config = [])
{
$this->connection = $connection;
Expand All @@ -28,7 +30,7 @@ public function __construct(AbstractConnection $connection, array $config = [])

public function getProducer(): Producer
{
return app()->make(Producer::class, ['connection' => $this->connection]);
return $this->producer ??= app()->make(Producer::class, ['connection' => $this->connection]);
}

public function getConsumer(array $options = []): Consumer
Expand Down
43 changes: 35 additions & 8 deletions tests/AmqpTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ public static function consumerConfigTestDataProvider(): array
/**
* @dataProvider publishMessageTestDataProvider
*
* @param array $data
* @param array $data
*/
public function testPublishFormatsMessagesToProducible(array $data)
{
Expand Down Expand Up @@ -432,7 +432,7 @@ public function testPublishPassesExpectedRoutingKey()
/**
* @dataProvider publishOptionsDataProvider
*
* @param array $data
* @param array $data
*/
public function testPublishPassesPublishOptionsIfAvailable(array $data)
{
Expand Down Expand Up @@ -471,7 +471,7 @@ function ($options) use ($expectations) {
/**
* @dataProvider exchangeTestDataProvider
*
* @param array $data
* @param array $data
*/
public function testPublishMessageProcessesExchange(array $data)
{
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -563,7 +590,7 @@ function () {
/**
* @dataProvider exchangeTestDataProvider
*
* @param array $data
* @param array $data
*/
public function testConsumerProcessesExchange(array $data)
{
Expand Down Expand Up @@ -611,7 +638,7 @@ function () {
/**
* @dataProvider queueTestDataProvider
*
* @param array $data
* @param array $data
*/
public function testConsumerProcessesQueue(array $data)
{
Expand Down Expand Up @@ -659,7 +686,7 @@ function () {
/**
* @dataProvider qosTestDataProvider
*
* @param array $data
* @param array $data
*/
public function testConsumerProcessesQos(array $data)
{
Expand Down Expand Up @@ -714,7 +741,7 @@ function () {
/**
* @dataProvider queueBindTestDataProvider
*
* @param array $data
* @param array $data
*/
public function testConsumerProcessesQueueBind(array $data)
{
Expand Down Expand Up @@ -762,7 +789,7 @@ function () {
/**
* @dataProvider consumerConfigTestDataProvider
*
* @param array $data
* @param array $data
*/
public function testConsumerProcessesConsumerConfig(array $data)
{
Expand Down

0 comments on commit d31c0aa

Please sign in to comment.