Skip to content

Commit

Permalink
feature #31334 [Messenger] Add clear Entity Manager middleware (Koc)
Browse files Browse the repository at this point in the history
This PR was merged into the 4.4 branch.

Discussion
----------

[Messenger] Add clear Entity Manager middleware

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #29662
| License       | MIT
| Doc PR        | TBD

General purpose of this middleware:
* avoid memory leaks during messages handling
* prevent unexpected side effects when entities that already stored in identity map not refreshed between messages

Commits
-------

6e690a6 Add clear Entity Manager middleware (closes #29662)
  • Loading branch information
fabpot committed Jun 4, 2019
2 parents 957a0b8 + 6e690a6 commit be7b7fe
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/Symfony/Bridge/Doctrine/CHANGELOG.md
@@ -1,6 +1,12 @@
CHANGELOG
=========

4.4.0
-----

* added `DoctrineClearEntityManagerMiddleware`


4.3.0
-----

Expand Down
@@ -0,0 +1,53 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\Doctrine\Messenger;

use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Middleware\StackInterface;

/**
* Clears entity manager after calling all handlers.
*
* @author Konstantin Myakshin <molodchick@gmail.com>
*/
class DoctrineClearEntityManagerMiddleware implements MiddlewareInterface
{
private $managerRegistry;
private $entityManagerName;

public function __construct(ManagerRegistry $managerRegistry, string $entityManagerName = null)
{
$this->managerRegistry = $managerRegistry;
$this->entityManagerName = $entityManagerName;
}

/**
* {@inheritdoc}
*/
public function handle(Envelope $envelope, StackInterface $stack): Envelope
{
try {
$entityManager = $this->managerRegistry->getManager($this->entityManagerName);
} catch (\InvalidArgumentException $e) {
throw new UnrecoverableMessageHandlingException($e->getMessage(), 0, $e);
}

try {
return $stack->next()->handle($envelope, $stack);
} finally {
$entityManager->clear();
}
}
}
@@ -0,0 +1,54 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\Doctrine\Tests\Messenger;

use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\Messenger\DoctrineClearEntityManagerMiddleware;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase;

class DoctrineClearEntityManagerMiddlewareTest extends MiddlewareTestCase
{
public function testMiddlewareClearEntityManager()
{
$entityManager = $this->createMock(EntityManagerInterface::class);
$entityManager->expects($this->once())
->method('clear');

$managerRegistry = $this->createMock(ManagerRegistry::class);
$managerRegistry
->method('getManager')
->with('default')
->willReturn($entityManager);

$middleware = new DoctrineClearEntityManagerMiddleware($managerRegistry, 'default');

$middleware->handle(new Envelope(new \stdClass()), $this->getStackMock());
}

public function testInvalidEntityManagerThrowsException()
{
$managerRegistry = $this->createMock(ManagerRegistry::class);
$managerRegistry
->method('getManager')
->with('unknown_manager')
->will($this->throwException(new \InvalidArgumentException()));

$middleware = new DoctrineClearEntityManagerMiddleware($managerRegistry, 'unknown_manager');

$this->expectException(UnrecoverableMessageHandlingException::class);

$middleware->handle(new Envelope(new \stdClass()), $this->getStackMock(false));
}
}

0 comments on commit be7b7fe

Please sign in to comment.