New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Messenger] Add a middleware that wraps all handlers in one Doctrine transaction. #26647
Changes from all commits
e62a0c9
78f021d
50f2cb8
11a3aab
373a2d4
4f54988
1eb6f4d
8b87f2b
a32e6b8
0261a51
f362f50
a629620
05ac7cf
0e0ab07
af65748
701c665
b336d04
7d84394
09e5daf
dcb07ca
1603708
399f7c5
5a6b8de
68131f4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?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 Doctrine\ORM\EntityManagerInterface; | ||
use Symfony\Component\Messenger\MiddlewareInterface; | ||
|
||
/** | ||
* Wraps all handlers in a single doctrine transaction. | ||
* | ||
* @author Tobias Nyholm <tobias.nyholm@gmail.com> | ||
*/ | ||
class DoctrineTransactionMiddleware implements MiddlewareInterface | ||
{ | ||
private $managerRegistry; | ||
private $entityManagerName; | ||
|
||
public function __construct(ManagerRegistry $managerRegistry, ?string $entityManagerName) | ||
{ | ||
$this->managerRegistry = $managerRegistry; | ||
$this->entityManagerName = $entityManagerName; | ||
} | ||
|
||
public function handle($message, callable $next) | ||
{ | ||
$entityManager = $this->managerRegistry->getManager($this->entityManagerName); | ||
|
||
if (!$entityManager instanceof EntityManagerInterface) { | ||
throw new \InvalidArgumentException(sprintf('The ObjectManager with name "%s" must be an instance of EntityManagerInterface', $this->entityManagerName)); | ||
} | ||
|
||
$entityManager->getConnection()->beginTransaction(); | ||
try { | ||
$result = $next($message); | ||
$entityManager->flush(); | ||
$entityManager->getConnection()->commit(); | ||
} catch (\Throwable $exception) { | ||
$entityManager->getConnection()->rollBack(); | ||
|
||
throw $exception; | ||
} | ||
|
||
return $result; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -969,13 +969,27 @@ private function addMessengerSection(ArrayNodeDefinition $rootNode) | |
->children() | ||
->arrayNode('routing') | ||
->useAttributeAsKey('message_class') | ||
->beforeNormalization() | ||
->always() | ||
->then(function ($config) { | ||
$newConfig = array(); | ||
foreach ($config as $k => $v) { | ||
if (!is_int($k)) { | ||
$newConfig[$k] = array('senders' => is_array($v) ? array_values($v) : array($v)); | ||
} else { | ||
$newConfig[$v['message-class']]['senders'] = array_map( | ||
function ($a) { | ||
return is_string($a) ? $a : $a['service']; | ||
}, | ||
array_values($v['sender']) | ||
); | ||
} | ||
} | ||
|
||
return $newConfig; | ||
}) | ||
->end() | ||
->prototype('array') | ||
->beforeNormalization() | ||
->ifString() | ||
->then(function ($v) { | ||
return array('senders' => array($v)); | ||
}) | ||
->end() | ||
->children() | ||
->arrayNode('senders') | ||
->requiresAtLeastOneElement() | ||
|
@@ -984,6 +998,16 @@ private function addMessengerSection(ArrayNodeDefinition $rootNode) | |
->end() | ||
->end() | ||
->end() | ||
->arrayNode('middlewares') | ||
->addDefaultsIfNotSet() | ||
->children() | ||
->arrayNode('doctrine_transaction') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should not be configured via Framework, but via DoctrineBundle. We don't have any other Doctrine config here AFAIR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @fabpot are you happy about the middleware being in the bridge, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #26684 is in. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also think this makes sense as is. Moving it to doctrine bundle would mean configuring messenger middlewares in two different places, I can't think of a good final result. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with @chalasr , it's only a feature flag. It does no harm having this in the fwb whereas having to configure middlewares in 2 different config keys is really bad, DX wise. WDYT? |
||
->canBeEnabled() | ||
->children() | ||
->scalarNode('entity_manager_name')->info('The name of the entity manager to use')->defaultNull()->end() | ||
->end() | ||
->end() | ||
->end() | ||
->end() | ||
->end() | ||
->end() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
$container->loadFromExtension('framework', array( | ||
'messenger' => array( | ||
'routing' => array( | ||
'App\Bar' => array('sender.bar', 'sender.biz'), | ||
'App\Foo' => 'sender.foo', | ||
), | ||
), | ||
)); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
$container->loadFromExtension('framework', array( | ||
'messenger' => array( | ||
'middlewares' => array( | ||
'doctrine_transaction' => array( | ||
'entity_manager_name' => 'foobar', | ||
), | ||
), | ||
), | ||
)); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<container xmlns="http://symfony.com/schema/dic/services" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xmlns:framework="http://symfony.com/schema/dic/symfony" | ||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd | ||
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> | ||
|
||
<framework:config> | ||
<framework:messenger> | ||
<framework:routing message-class="App\Bar"> | ||
<framework:sender service="sender.bar" /> | ||
<framework:sender service="sender.biz" /> | ||
</framework:routing> | ||
<framework:routing message-class="App\Foo"> | ||
<framework:sender service="sender.foo" /> | ||
</framework:routing> | ||
</framework:messenger> | ||
</framework:config> | ||
</container> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<container xmlns="http://symfony.com/schema/dic/services" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xmlns:framework="http://symfony.com/schema/dic/symfony" | ||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd | ||
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> | ||
|
||
<framework:config> | ||
<framework:messenger> | ||
<framework:middlewares> | ||
<framework:doctrine-transaction entity-manager-name="foobar" /> | ||
</framework:middlewares> | ||
</framework:messenger> | ||
</framework:config> | ||
</container> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
framework: | ||
messenger: | ||
routing: | ||
'App\Bar': ['sender.bar', 'sender.biz'] | ||
'App\Foo': 'sender.foo' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
framework: | ||
messenger: | ||
middlewares: | ||
doctrine_transaction: | ||
entity_manager_name: 'foobar' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing dot at the end of the exception message.