Skip to content

Commit 42880fc

Browse files
authored
Merge pull request #7 from alextcyinnovation/add-release-memory-middleware
Add ReleaseMemoryMiddleware. Add option to clear memory before or after processing message
2 parents 42b984c + 27b903e commit 42880fc

4 files changed

Lines changed: 120 additions & 0 deletions

File tree

src/DependencyInjection/AmqpExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ private function configureExchanges(ContainerBuilder $container, array $exchange
340340
$exchangeFactoryServiceId = \sprintf('fivelab.amqp.exchange_factory.%s', $key);
341341
$exchangeFactoryServiceDef = new Definition(ExchangeFactoryInterface::class);
342342
$exchangeFactoryServiceDef->setFactory([new Reference($this->driverFactories[$exchange['connection']]), 'createExchangeFactory']);
343+
343344
$exchangeFactoryServiceDef->setArguments([
344345
new Reference($this->defaultChannelFactories[$exchange['connection']]),
345346
new Reference($exchangeDefinitionServiceId),
@@ -496,6 +497,7 @@ private function configureQueues(ContainerBuilder $container, array $queues, arr
496497
$queueFactoryServiceId = \sprintf('fivelab.amqp.queue_factory.%s', $key);
497498
$queueFactoryServiceDef = new Definition(QueueFactoryInterface::class);
498499
$queueFactoryServiceDef->setFactory([new Reference($this->driverFactories[$queue['connection']]), 'createQueueFactory']);
500+
499501
$queueFactoryServiceDef->setArguments([
500502
new Reference($this->defaultChannelFactories[$queue['connection']]),
501503
new Reference($queueDefinitionServiceId),
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace FiveLab\Bundle\AmqpBundle\Middleware;
6+
7+
use FiveLab\Component\Amqp\Consumer\Middleware\ConsumerMiddlewareInterface;
8+
use FiveLab\Component\Amqp\Message\ReceivedMessage;
9+
use Symfony\Contracts\Service\ResetInterface;
10+
11+
class ReleaseMemoryMiddleware implements ConsumerMiddlewareInterface
12+
{
13+
public function __construct(private ResetInterface $servicesResetter, private bool $clearBeforeHandle = false)
14+
{
15+
}
16+
17+
public function handle(ReceivedMessage $message, callable $next): void
18+
{
19+
if (true === $this->clearBeforeHandle) {
20+
$this->resetMemory();
21+
}
22+
23+
try {
24+
$next($message);
25+
} finally {
26+
if (false === $this->clearBeforeHandle) {
27+
$this->resetMemory();
28+
}
29+
}
30+
}
31+
32+
private function resetMemory(): void
33+
{
34+
$this->servicesResetter->reset();
35+
36+
\gc_collect_cycles();
37+
}
38+
}

tests/DependencyInjection/AmqpExtensionConfigureConsumersTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public function shouldSuccessConfigureSingleConsumer(): void
123123

124124
// Verify registry
125125
$this->assertContainerBuilderHasService('fivelab.amqp.consumer_registry', ContainerConsumerRegistry::class);
126+
126127
$this->assertContainerBuilderHasServiceDefinitionWithServiceLocatorArgument('fivelab.amqp.consumer_registry', 0, [
127128
'foo' => 'fivelab.amqp.consumer.foo',
128129
]);
@@ -147,6 +148,7 @@ public function shouldSuccessConfigureWithChecker(): void
147148
]);
148149

149150
$this->assertContainerBuilderHasService('fivelab.amqp.consumer_checker_registry', ContainerRunConsumerCheckerRegistry::class);
151+
150152
$this->assertContainerBuilderHasServiceDefinitionWithServiceLocatorArgument('fivelab.amqp.consumer_checker_registry', 0, [
151153
'bla' => 'default_checker',
152154
]);
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the FiveLab AmqpBundle package
5+
*
6+
* (c) FiveLab
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code
10+
*/
11+
12+
declare(strict_types = 1);
13+
14+
namespace FiveLab\Bundle\AmqpBundle\Tests\Middleware;
15+
16+
use FiveLab\Bundle\AmqpBundle\Middleware\ReleaseMemoryMiddleware;
17+
use FiveLab\Component\Amqp\Message\ReceivedMessage;
18+
use PHPUnit\Framework\Attributes\Test;
19+
use PHPUnit\Framework\TestCase;
20+
use Symfony\Contracts\Service\ResetInterface;
21+
22+
class ReleaseMemoryMiddlewareTest extends TestCase
23+
{
24+
private ResetInterface $servicesResetter;
25+
26+
protected function setUp(): void
27+
{
28+
$this->servicesResetter = $this->createMock(ResetInterface::class);
29+
}
30+
31+
#[Test]
32+
public function clearMemoryBeforeMessage(): void
33+
{
34+
$alreadyReset = false;
35+
$message = $this->createMock(ReceivedMessage::class);
36+
37+
$next = function (ReceivedMessage $message) use (&$alreadyReset) {
38+
$this->assertTrue($alreadyReset);
39+
};
40+
41+
$this->servicesResetter
42+
->expects($this->once())
43+
->method('reset')
44+
->willReturnCallback(function () use (&$alreadyReset): void {
45+
$alreadyReset = true;
46+
});
47+
48+
$this->getMiddleware(true)->handle($message, $next);
49+
}
50+
51+
#[Test]
52+
public function clearMemoryOnlyAfterMessage(): void
53+
{
54+
$alreadyReset = false;
55+
$message = $this->createMock(ReceivedMessage::class);
56+
57+
$next = function (ReceivedMessage $message) use (&$alreadyReset) {
58+
$this->assertFalse($alreadyReset);
59+
};
60+
61+
$this->servicesResetter
62+
->expects($this->once())
63+
->method('reset')
64+
->willReturnCallback(function () use (&$alreadyReset): void {
65+
$alreadyReset = true;
66+
});
67+
68+
$this->getMiddleware(false)->handle($message, $next);
69+
}
70+
71+
private function getMiddleware(bool $clearBeforeMessage): ReleaseMemoryMiddleware
72+
{
73+
return new ReleaseMemoryMiddleware(
74+
$this->servicesResetter,
75+
$clearBeforeMessage
76+
);
77+
}
78+
}

0 commit comments

Comments
 (0)