Skip to content

Fix Doctrine's middlewares sorting #18874

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

Merged
merged 1 commit into from
Sep 18, 2023
Merged

Conversation

lruozzi9
Copy link
Contributor

If you place the doctrine_open_transaction_logger middleware after doctrine_transaction you will always get the error log because the first one is handled before the latter. So I think the order in that section should be reversed to avoid errors.

@javiereguiluz
Copy link
Member

javiereguiluz commented Sep 18, 2023

I haven't tested this myself, but current docs look OK to me. Looking at the code:

https://github.com/symfony/doctrine-bridge/blob/65d82374b47880b4ba1a11e1704aa68e7f76b88b/Messenger/DoctrineOpenTransactionLoggerMiddleware.php#L42-L46

The logger middleware checks if a transaction is open. So, if we run it before the transaction middleware, there will never be an open transaction. If we run it afterwards, we'll see if there's still an open transaction, right?

@lruozzi9
Copy link
Contributor Author

Hi @javiereguiluz! You're right but the order in definition must be reversed. Middlewares are invoked sequentially as they are defined and the next middleware is invoked from the inside of the current middleware. This means that after the message handling the middleware will be closed in reverse.
To better explain I make a simple example of the stack trace. The first one is with the current doc definition:

  1. DoctrineTransactionMiddleware::31 -> $stack->next()->handle($envelope, $stack); (the transaction has been started)
  2. DoctrineOpenTransactionLoggerMiddleware::40 -> $stack->next()->handle($envelope, $stack);
  3. Now the message handler is invoked and run.
  4. DoctrineOpenTransactionLoggerMiddleware::42 -> if ($entityManager->getConnection()->isTransactionActive()) { (yes! Here the transaction is still opened so it logs an error)
  5. DoctrineTransactionMiddleware -> If the message handler has been completed without errors the transaction will be committed, otherwise it will be rolled back. Anyway, here the transaction will be closed)

The right path should be:

  1. DoctrineOpenTransactionLoggerMiddleware::40 -> $stack->next()->handle($envelope, $stack);
  2. DoctrineTransactionMiddleware::31 -> $stack->next()->handle($envelope, $stack); (the transaction has been started)
  3. Now the message handler is invoked and run.
  4. DoctrineTransactionMiddleware -> If the message handler has been completed without errors the transaction will be committed, otherwise it will be rolled back. Anyway, here the transaction will be closed)
  5. DoctrineOpenTransactionLoggerMiddleware::42 -> if ($entityManager->getConnection()->isTransactionActive()) { (no! Here the transaction is now closed and any error will be logged!)

@javiereguiluz
Copy link
Member

Lorenzo, thanks a lot for your great explanation. Now I fully understand the issue. I've just merged your PR.

Thanks and congrats on your first Symfony Docs contribution 🎉

@javiereguiluz javiereguiluz merged commit 9059095 into symfony:6.3 Sep 18, 2023
@lruozzi9
Copy link
Contributor Author

Thanks! First of a long series hope! 😄

@lruozzi9 lruozzi9 deleted the patch-1 branch September 18, 2023 10:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants