Description
Symfony version(s) affected
6.4
Description
When using the doctrine transaction middleware, for each event dispatched, a transaction is started even if the message is not about to be handled yet. This results in useless "empty" transactions while the message is being sent.
This can lead to poor performance when dispatching many events synchronously
How to reproduce
You can dispatch many multiple events on a bus where the doctrine_transaction
is registered, go to the profiler and check the performance tab and the doctrine tab. Here I dispatched 96 events :
Possible Solution
By verifying that the ReceivedStamp
exists on the envelope before actually running the middleware, we get rid of those requests and things seems to work properly (I do not see a case where it would not but I might be wrong). In my case, it resulted in huge performance boost on production :
class DoctrineTransactionMiddleware extends AbstractDoctrineMiddleware
{
protected function handleForManager(EntityManagerInterface $entityManager, Envelope $envelope, StackInterface $stack): Envelope
{
if (!$envelope->last(ReceivedStamp::class) instanceof StampInterface) {
return $stack->next()->handle($envelope, $stack);
}
$entityManager->getConnection()->beginTransaction();
$success = false;
try {
$envelope = $stack->next()->handle($envelope, $stack);
$entityManager->flush();
$entityManager->getConnection()->commit();
$success = true;
return $envelope;
} catch (\Throwable $exception) {
if ($exception instanceof HandlerFailedException) {
// Remove all HandledStamp from the envelope so the retry will execute all handlers again.
// When a handler fails, the queries of allegedly successful previous handlers just got rolled back.
throw new HandlerFailedException($exception->getEnvelope()->withoutAll(HandledStamp::class), $exception->getWrappedExceptions());
}
throw $exception;
} finally {
$connection = $entityManager->getConnection();
if (!$success && $connection->isTransactionActive()) {
$connection->rollBack();
}
}
}
}
Additional Context
No response