Skip to content
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

[10.x] Fix "after commit" callbacks not running on nested transactions using RefreshDatabase or DatabaseMigrations #48523

Merged
merged 79 commits into from
Sep 26, 2023

Conversation

crynobone
Copy link
Member

@crynobone crynobone commented Sep 25, 2023

Separate db.transactions instance between normal requests and tests. PR based from #48466 and fixes #48451

tonysm and others added 30 commits September 20, 2023 00:56
Signed-off-by: Mior Muhammad Zaki <[email protected]>
Signed-off-by: Mior Muhammad Zaki <[email protected]>
Signed-off-by: Mior Muhammad Zaki <[email protected]>
to avoid remembering which transactions to ignore

Before, we were remembering the test transaction so we
could ignore it when deciding to run the after commit
callbacks or not.

We're still handling the after commit callbacks like that
but now instead of remembering which transactions to ignore,
we're always calling the DatabaseTransactionManager::commit
method. The difference is that now we're passing the current
transaction level to it. The method will decide to call the
callbacks or not based on that level and whether or not this
is on in test mode.

When in tests, instead of setting the current transaction to be
remembered so it could be ignored, we're now only setting the
DatabaseTransactionManager to test mode. When in test mode, it
will execute the callbacks when the transactions count reaches
1 (remember that the test runs in a transaction, so that's the
"root" level). Otherwise, it runs the callbacks when the transactions
level is on level 0 (like in production).

There's also a change in the DatabaseTransactionManager::addCallback
method. It now also checks if it's in test mode. When not in test mode,
it only adds the callback to the execution queue if there's an open
transaction. Otherwise, the callback is executed right away. When in
test mode, the number of transactions has to be greater than one for
it to be added to the callbacks queue.
Signed-off-by: Mior Muhammad Zaki <[email protected]>
Signed-off-by: Mior Muhammad Zaki <[email protected]>
Signed-off-by: Mior Muhammad Zaki <[email protected]>
Signed-off-by: Mior Muhammad Zaki <[email protected]>
Signed-off-by: Mior Muhammad Zaki <[email protected]>
Signed-off-by: Mior Muhammad Zaki <[email protected]>
Signed-off-by: Mior Muhammad Zaki <[email protected]>
Signed-off-by: Mior Muhammad Zaki <[email protected]>
@mpyw
Copy link
Contributor

mpyw commented Sep 25, 2023

Great work!!!!!!!!

Signed-off-by: Mior Muhammad Zaki <[email protected]>
Signed-off-by: Mior Muhammad Zaki <[email protected]>
@crynobone crynobone marked this pull request as draft September 25, 2023 14:31
@crynobone crynobone marked this pull request as ready for review September 25, 2023 14:36
@crynobone
Copy link
Member Author

Will need to retest if the tests actually still breaking without the code changes after #48531

Marking this as draft.

@crynobone crynobone marked this pull request as draft September 25, 2023 14:43
@tonysm
Copy link
Contributor

tonysm commented Sep 25, 2023

@crynobone Nice work! I think it will still be needed, even after #48531, because it's more about nested transactions on tests, which was only surfaced by the createOrFirst method... so I think it's still worth it.

@crynobone
Copy link
Member Author

crynobone commented Sep 26, 2023

Verified this changes still solve transaction + after commit issue using RefreshDatabase. See #48545

@crynobone crynobone marked this pull request as ready for review September 26, 2023 05:35
@taylorotwell taylorotwell merged commit ebcb151 into 10.x Sep 26, 2023
20 of 21 checks passed
@taylorotwell taylorotwell deleted the 48466-redux branch September 26, 2023 21:42
@taylorotwell
Copy link
Member

Thanks!

timacdonald pushed a commit to timacdonald/framework that referenced this pull request Sep 27, 2023
…s using `RefreshDatabase` or `DatabaseMigrations` (laravel#48523)

* Tests observer using afterCommit

* Adds failing test for savepoint and observers using afterCommit

* Ignore the createOrFirst savepoint to run callbacks

* Fix typo

* Remove DatabaseEloquentAppTest to see if CI passes

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* Update src/Illuminate/Database/DatabaseTransactionsManager.php

Co-authored-by: Mior Muhammad Zaki <[email protected]>

* Changes the way the after commit callbacks are executed
to avoid remembering which transactions to ignore

Before, we were remembering the test transaction so we
could ignore it when deciding to run the after commit
callbacks or not.

We're still handling the after commit callbacks like that
but now instead of remembering which transactions to ignore,
we're always calling the DatabaseTransactionManager::commit
method. The difference is that now we're passing the current
transaction level to it. The method will decide to call the
callbacks or not based on that level and whether or not this
is on in test mode.

When in tests, instead of setting the current transaction to be
remembered so it could be ignored, we're now only setting the
DatabaseTransactionManager to test mode. When in test mode, it
will execute the callbacks when the transactions count reaches
1 (remember that the test runs in a transaction, so that's the
"root" level). Otherwise, it runs the callbacks when the transactions
level is on level 0 (like in production).

There's also a change in the DatabaseTransactionManager::addCallback
method. It now also checks if it's in test mode. When not in test mode,
it only adds the callback to the execution queue if there's an open
transaction. Otherwise, the callback is executed right away. When in
test mode, the number of transactions has to be greater than one for
it to be added to the callbacks queue.

* Fix DatabaseTransactionsTest

* Fix DatabaseTransactionsManagerTest

* CSFixer

* wip

* Rename method and property and inline usage

* Adds a depply nested transaction test

* Simplify deeply nesting test

* Sets default level value to one (since it's a new parameter)

* Rename method

* Adds back the removed methods from the db.transactions and mark them as deprecated

* StyleCI

* Inline the if statement using then collection when() method

* Tests observer using afterCommit

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* Apply fixes from StyleCI

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* Apply fixes from StyleCI

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* Apply fixes from StyleCI

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* Apply fixes from StyleCI

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* Apply fixes from StyleCI

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* Update src/Illuminate/Foundation/Testing/DatabaseTransactionsManager.php

Co-authored-by: Tony Messias <[email protected]>

* Update src/Illuminate/Database/DatabaseTransactionsManager.php

* formatting

---------

Signed-off-by: Mior Muhammad Zaki <[email protected]>
Co-authored-by: Tony Messias <[email protected]>
Co-authored-by: Taylor Otwell <[email protected]>
Co-authored-by: StyleCI Bot <[email protected]>
@azgooon
Copy link

azgooon commented Oct 6, 2023

Hey @tonysm, the project I am working on uses nested transactions and they used to work flawlesly however I've updated laravel framework and now I keep getting errors:
PDOException: SQLSTATE[25P01]: No active sql transaction: 7 ERROR: SAVEPOINT can only be used in transaction blocks in /var/www/vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php:159
I decided to check recent commits in laravel project and came accross this one, I suspect that this change could be responsible for this error. Could you please assist?

I just reverted back to v10.25.0 and the problem has gone away, then changed to v10.25.1 and problem re-appeared.

@mpyw
Copy link
Contributor

mpyw commented Oct 6, 2023

Hi @azgooon

Are you consistently using DB::transaction() instead of independent DB::beginTransaction() DB::commit()?

@crynobone
Copy link
Member Author

This PR only change behaviour while running tests and doesn't affect your application code. Submit new bug report with reproducing code.

@azgooon
Copy link

azgooon commented Oct 6, 2023

Hi @mpyw yes, DB::transaction() is the approach we use.

@tonysm
Copy link
Contributor

tonysm commented Oct 6, 2023

@azgooon Which database are you using and can you share a test where this issue appears (if you can reduce it down to a simple test, that would be great)? As @crynobone mentioned, the changes here should only affect tests, so I assume your tests failed, right? Pls share more context on the tests, which traits you're using and things like that. Thanks!

@azgooon
Copy link

azgooon commented Oct 6, 2023

@tonysm I will happily provide as much details as I can. To start from I am not refering to the test as we don't have any. I was refering to the actual functionality of the project which partially stopped working in places where DB::transaction calls methods which are also performing DB::transaction(); Please bear with me a while, I will do my best to extract a piece of code which does not work anymore, We use PostgreSQL.

@crynobone
Copy link
Member Author

Not related to this PR, please compile new bug report with reproducing code and continue there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RefreshDatabase + double wrapping in DB::transaction() breaks $afterCommit functionality
6 participants