Skip to content
65 changes: 65 additions & 0 deletions MemoryChecker/MemoryConsumptionChecker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace OldSound\RabbitMqBundle\MemoryChecker;

/**
* Help handling memory limits .
*
* @author Jonas Haouzi <jonas@viscaweb.com>
*/
class MemoryConsumptionChecker
{
/** @var NativeMemoryUsageProvider */
private $memoryUsageProvider;

/**
* MemoryManager constructor.
*
* @param NativeMemoryUsageProvider $memoryUsageProvider
*/
public function __construct(NativeMemoryUsageProvider $memoryUsageProvider) {
$this->memoryUsageProvider = $memoryUsageProvider;
}

/**
* @param int|string $allowedConsumptionUntil
* @param int|string $maxConsumptionAllowed
*
* @return bool
*/
public function isRamAlmostOverloaded($allowedConsumptionUntil, $maxConsumptionAllowed)
{
$allowedConsumptionUntil = $this->convertHumanUnitToNumerical($allowedConsumptionUntil);
$maxConsumptionAllowed = $this->convertHumanUnitToNumerical($maxConsumptionAllowed);
$currentUsage = $this->convertHumanUnitToNumerical($this->memoryUsageProvider->getMemoryUsage());

return $currentUsage > ($maxConsumptionAllowed - $allowedConsumptionUntil);
}

/**
* @param int|string $humanUnit
*
* @return int
*/
private function convertHumanUnitToNumerical($humanUnit)
{
$numerical = $humanUnit;
if (!is_numeric($humanUnit)) {
$numerical = substr($numerical, 0, -1);
switch (substr($humanUnit, -1)) {
case 'G':
$numerical *= pow(1024, 3);
break;
case 'M':
$numerical *= pow(1024, 2);
break;
case 'K':
$numerical *= 1024;
break;
}
}

return (int)$numerical;
}

}
19 changes: 19 additions & 0 deletions MemoryChecker/NativeMemoryUsageProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace OldSound\RabbitMqBundle\MemoryChecker;

/**
* Returns the current memory PHP is using (mainly used to allow mocking).
*
* @author Jonas Haouzi <jonas@viscaweb.com>
*/
class NativeMemoryUsageProvider
{
/**
* @return int
*/
public function getMemoryUsage()
{
return memory_get_usage(true);
}
}
10 changes: 5 additions & 5 deletions RabbitMq/Consumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use OldSound\RabbitMqBundle\Event\AfterProcessingMessageEvent;
use OldSound\RabbitMqBundle\Event\BeforeProcessingMessageEvent;
use OldSound\RabbitMqBundle\Event\OnConsumeEvent;
use OldSound\RabbitMqBundle\MemoryChecker\MemoryConsumptionChecker;
use OldSound\RabbitMqBundle\MemoryChecker\NativeMemoryUsageProvider;
use PhpAmqpLib\Exception\AMQPTimeoutException;
use PhpAmqpLib\Message\AMQPMessage;

Expand Down Expand Up @@ -164,10 +166,8 @@ protected function handleProcessMessage(AMQPMessage $msg, $processFlag)
*/
protected function isRamAlmostOverloaded()
{
if (memory_get_usage(true) >= ($this->getMemoryLimit() * 1024 * 1024)) {
return true;
} else {
return false;
}
$memoryManager = new MemoryConsumptionChecker(new NativeMemoryUsageProvider());

return $memoryManager->isRamAlmostOverloaded($this->getMemoryLimit(), '5M');
}
}
42 changes: 42 additions & 0 deletions Tests/Manager/MemoryCheckerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace OldSound\RabbitMqBundle\Tests\Event;

use OldSound\RabbitMqBundle\MemoryChecker\MemoryConsumptionChecker;
use OldSound\RabbitMqBundle\MemoryChecker\NativeMemoryUsageProvider;

/**
* Class MemoryManagerTest
*
* @package OldSound\RabbitMqBundle\Tests\Manager
*/
class MemoryConsumptionCheckerTest extends \PHPUnit_Framework_TestCase
{
public function testMemoryIsNotAlmostOverloaded()
{
$currentMemoryUsage = '7M';
$allowedConsumptionUntil = '2M';
$maxConsumptionAllowed = '10M';

$memoryUsageProvider = $this->getMockBuilder(NativeMemoryUsageProvider::class)->getMock();
$memoryUsageProvider->expects($this->any())->method('getMemoryUsage')->willReturn($currentMemoryUsage);

$memoryManager = new MemoryConsumptionChecker($memoryUsageProvider);

$this->assertFalse($memoryManager->isRamAlmostOverloaded($allowedConsumptionUntil, $maxConsumptionAllowed));
}

public function testMemoryIsAlmostOverloaded()
{
$currentMemoryUsage = '9M';
$allowedConsumptionUntil = '2M';
$maxConsumptionAllowed = '10M';

$memoryUsageProvider = $this->getMockBuilder(NativeMemoryUsageProvider::class)->getMock();
$memoryUsageProvider->expects($this->any())->method('getMemoryUsage')->willReturn($currentMemoryUsage);

$memoryManager = new MemoryConsumptionChecker($memoryUsageProvider);

$this->assertTrue($memoryManager->isRamAlmostOverloaded($allowedConsumptionUntil, $maxConsumptionAllowed));
}
}