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
Changes from 76 commits
Commits
Show all changes
79 commits
Select commit
Hold shift + click to select a range
1f10b5e
Tests observer using afterCommit
tonysm d9538d6
Adds failing test for savepoint and observers using afterCommit
tonysm e6de881
Ignore the createOrFirst savepoint to run callbacks
tonysm 06adc98
Fix typo
tonysm bf2764b
Remove DatabaseEloquentAppTest to see if CI passes
tonysm 451fd8b
wip
crynobone f49260e
wip
crynobone a7a2fa2
wip
crynobone e3df8b1
Update src/Illuminate/Database/DatabaseTransactionsManager.php
taylorotwell f5aacf5
Changes the way the after commit callbacks are executed
tonysm 1d7b8ee
Fix DatabaseTransactionsTest
tonysm 65c75ae
Fix DatabaseTransactionsManagerTest
tonysm 2037453
CSFixer
tonysm c7c7f3a
wip
tonysm 0d8f1fa
Rename method and property and inline usage
tonysm 393a69c
Adds a depply nested transaction test
tonysm d3dcb03
Simplify deeply nesting test
tonysm 68ed29a
Sets default level value to one (since it's a new parameter)
tonysm 5825929
Rename method
tonysm c660879
Adds back the removed methods from the db.transactions and mark them …
tonysm e111e70
StyleCI
tonysm 239e6ec
Inline the if statement using then collection when() method
tonysm 3510970
Tests observer using afterCommit
tonysm 7bb02ae
wip
crynobone 6799bde
wip
crynobone 9cc6900
wip
crynobone ad9b10c
wip
crynobone 4a0232b
wip
crynobone 36f1d21
wip
crynobone 2f3a943
wip
crynobone 1e8bcf4
Apply fixes from StyleCI
StyleCIBot f245912
wip
crynobone be843ef
wip
crynobone 6519d0d
wip
crynobone e2a079b
wip
crynobone 21c6548
wip
crynobone 5863f0c
wip
crynobone 7571318
wip
crynobone a8882f5
wip
crynobone d4ec4a2
Apply fixes from StyleCI
StyleCIBot 8e9eae3
wip
crynobone d2266a2
Merge remote-tracking branch 'upstream/48466-redux' into 48466-redux
crynobone 9968ad2
wip
crynobone b3c3951
wip
crynobone d13db21
wip
crynobone e599333
wip
crynobone 7c99f62
Apply fixes from StyleCI
StyleCIBot c645396
wip
crynobone b1decbf
Merge branch 'fix-create-or-first-transaction-callbacks' into 48466-r…
crynobone 4f93300
wip
crynobone 1e93349
Apply fixes from StyleCI
StyleCIBot 082f4f5
wip
crynobone 9514f3b
Merge remote-tracking branch 'upstream/48466-redux' into 48466-redux
crynobone f5877c2
wip
crynobone 8ff509f
wip
crynobone 55e7044
wip
crynobone 9474b23
wip
crynobone a7aa391
wip
crynobone f9ccf6c
wip
crynobone 410bb9c
wip
crynobone 1ae7684
wip
crynobone bc9a4d5
Apply fixes from StyleCI
StyleCIBot 8c503a3
wip
crynobone f81cab0
Merge remote-tracking branch 'upstream/48466-redux' into 48466-redux
crynobone 9a3a21e
wip
crynobone 8beb730
wip
crynobone 541af7b
wip
crynobone 9aa3c32
wip
crynobone c107aec
wip
crynobone 565c579
wip
crynobone 0542d0e
wip
crynobone 95dfe34
wip
crynobone 34f3933
wip
crynobone 7dd9c57
wip
crynobone bcedae8
Merge branch '10.x' into 48466-redux
crynobone c291c3a
Merge branch '10.x' into 48466-redux
crynobone 681154c
Update src/Illuminate/Foundation/Testing/DatabaseTransactionsManager.php
crynobone fa66e08
Update src/Illuminate/Database/DatabaseTransactionsManager.php
crynobone a519fde
formatting
taylorotwell File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
src/Illuminate/Foundation/Testing/DatabaseTransactionsManager.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?php | ||
|
||
namespace Illuminate\Foundation\Testing; | ||
|
||
class DatabaseTransactionsManager extends \Illuminate\Database\DatabaseTransactionsManager | ||
{ | ||
/** | ||
* Register a transaction callback. | ||
* | ||
* @param callable $callback | ||
* @return void | ||
*/ | ||
public function addCallback($callback) | ||
{ | ||
// If there are no transactions, we'll run the callbacks right away. Also, we'll run it | ||
// right away when we're in test mode and we only have the wrapping transaction. For | ||
// every other case, we'll queue up the callback to run after the commit happens. | ||
if ($this->callbackApplicableTransactions()->count() === 0) { | ||
return $callback(); | ||
} | ||
|
||
$this->transactions->last()->addCallback($callback); | ||
} | ||
|
||
/** | ||
* Get the transactions that are applicable to callbacks. | ||
* | ||
* @return \Illuminate\Support\Collection<int, \Illuminate\Database\DatabaseTransactionRecord> | ||
*/ | ||
public function callbackApplicableTransactions() | ||
{ | ||
return $this->transactions->reject( | ||
fn ($transaction) => $transaction === $this->transactions->first() | ||
)->values(); | ||
crynobone marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
/** | ||
* Determine if after commit callbacks should be executed. | ||
* | ||
* @param int $level | ||
* @return bool | ||
*/ | ||
public function afterCommitCallbacksShouldBeExecuted($level) | ||
{ | ||
return $level === 2; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
tests/Integration/Database/EloquentTransactionWithAfterCommitTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?php | ||
|
||
namespace Illuminate\Tests\Integration\Database; | ||
|
||
class EloquentTransactionWithAfterCommitTest extends DatabaseTestCase | ||
{ | ||
use EloquentTransactionWithAfterCommitTests; | ||
} |
104 changes: 104 additions & 0 deletions
104
tests/Integration/Database/EloquentTransactionWithAfterCommitTests.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<?php | ||
|
||
namespace Illuminate\Tests\Integration\Database; | ||
|
||
use Illuminate\Foundation\Auth\User; | ||
use Illuminate\Support\Facades\DB; | ||
use Orchestra\Testbench\Concerns\WithLaravelMigrations; | ||
use Orchestra\Testbench\Factories\UserFactory; | ||
|
||
trait EloquentTransactionWithAfterCommitTests | ||
{ | ||
use WithLaravelMigrations; | ||
|
||
protected function setUpEloquentTransactionWithAfterCommitTests(): void | ||
{ | ||
User::unguard(); | ||
} | ||
|
||
protected function tearDownEloquentTransactionWithAfterCommitTests(): void | ||
{ | ||
User::reguard(); | ||
} | ||
|
||
public function testObserverIsCalledOnTestsWithAfterCommit() | ||
{ | ||
User::observe($observer = EloquentTransactionWithAfterCommitTestsUserObserver::resetting()); | ||
|
||
$user1 = User::create(UserFactory::new()->raw()); | ||
|
||
$this->assertTrue($user1->exists); | ||
$this->assertEquals(1, $observer::$calledTimes, 'Failed to assert the observer was called once.'); | ||
} | ||
|
||
public function testObserverCalledWithAfterCommitWhenInsideTransaction() | ||
{ | ||
User::observe($observer = EloquentTransactionWithAfterCommitTestsUserObserver::resetting()); | ||
|
||
$user1 = DB::transaction(fn () => User::create(UserFactory::new()->raw())); | ||
|
||
$this->assertTrue($user1->exists); | ||
$this->assertEquals(1, $observer::$calledTimes, 'Failed to assert the observer was called once.'); | ||
} | ||
|
||
public function testObserverIsCalledOnTestsWithAfterCommitWhenUsingSavepoint() | ||
{ | ||
User::observe($observer = EloquentTransactionWithAfterCommitTestsUserObserver::resetting()); | ||
|
||
$user1 = User::createOrFirst(UserFactory::new()->raw()); | ||
|
||
$this->assertTrue($user1->exists); | ||
$this->assertEquals(1, $observer::$calledTimes, 'Failed to assert the observer was called once.'); | ||
} | ||
|
||
public function testObserverIsCalledOnTestsWithAfterCommitWhenUsingSavepointAndInsideTransaction() | ||
{ | ||
User::observe($observer = EloquentTransactionWithAfterCommitTestsUserObserver::resetting()); | ||
|
||
$user1 = DB::transaction(fn () => User::createOrFirst(UserFactory::new()->raw())); | ||
|
||
$this->assertTrue($user1->exists); | ||
$this->assertEquals(1, $observer::$calledTimes, 'Failed to assert the observer was called once.'); | ||
} | ||
|
||
public function testObserverIsCalledEvenWhenDeeplyNestingTransactions() | ||
{ | ||
User::observe($observer = EloquentTransactionWithAfterCommitTestsUserObserver::resetting()); | ||
|
||
$user1 = DB::transaction(function () use ($observer) { | ||
return tap(DB::transaction(function () use ($observer) { | ||
return tap(DB::transaction(function () use ($observer) { | ||
return tap(User::createOrFirst(UserFactory::new()->raw()), function () use ($observer) { | ||
$this->assertEquals(0, $observer::$calledTimes, 'Should not have been called'); | ||
}); | ||
}), function () use ($observer) { | ||
$this->assertEquals(0, $observer::$calledTimes, 'Should not have been called'); | ||
}); | ||
}), function () use ($observer) { | ||
$this->assertEquals(0, $observer::$calledTimes, 'Should not have been called'); | ||
}); | ||
}); | ||
|
||
$this->assertTrue($user1->exists); | ||
$this->assertEquals(1, $observer::$calledTimes, 'Failed to assert the observer was called once.'); | ||
} | ||
} | ||
|
||
class EloquentTransactionWithAfterCommitTestsUserObserver | ||
{ | ||
public static $calledTimes = 0; | ||
|
||
public $afterCommit = true; | ||
|
||
public static function resetting() | ||
{ | ||
static::$calledTimes = 0; | ||
|
||
return new static(); | ||
} | ||
|
||
public function created($user) | ||
{ | ||
static::$calledTimes++; | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
tests/Integration/Database/EloquentTransactionWithAfterCommitUsingDatabaseMigrationsTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
namespace Illuminate\Tests\Integration\Database; | ||
|
||
use Illuminate\Foundation\Testing\DatabaseMigrations; | ||
|
||
class EloquentTransactionWithAfterCommitUsingDatabaseMigrationsTest extends DatabaseTestCase | ||
{ | ||
use EloquentTransactionWithAfterCommitTests; | ||
use DatabaseMigrations; | ||
} |
41 changes: 41 additions & 0 deletions
41
.../Integration/Database/EloquentTransactionWithAfterCommitUsingDatabaseTransactionsTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?php | ||
|
||
namespace Illuminate\Tests\Integration\Database; | ||
|
||
use Illuminate\Foundation\Testing\DatabaseTransactions; | ||
use Orchestra\Testbench\TestCase; | ||
|
||
class EloquentTransactionWithAfterCommitUsingDatabaseTransactionsTest extends TestCase | ||
{ | ||
use EloquentTransactionWithAfterCommitTests; | ||
use DatabaseTransactions; | ||
|
||
/** | ||
* The current database driver. | ||
* | ||
* @return string | ||
*/ | ||
protected $driver; | ||
|
||
protected function setUp(): void | ||
{ | ||
$this->beforeApplicationDestroyed(function () { | ||
foreach (array_keys($this->app['db']->getConnections()) as $name) { | ||
$this->app['db']->purge($name); | ||
} | ||
}); | ||
|
||
parent::setUp(); | ||
|
||
if ($this->usesSqliteInMemoryDatabaseConnection()) { | ||
$this->markTestSkipped('Test cannot be used with in-memory SQLite connection.'); | ||
} | ||
} | ||
|
||
protected function getEnvironmentSetUp($app) | ||
{ | ||
$connection = $app->make('config')->get('database.default'); | ||
|
||
$this->driver = $app['config']->get("database.connections.$connection.driver"); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
tests/Integration/Database/EloquentTransactionWithAfterCommitUsingRefreshDatabaseTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?php | ||
|
||
namespace Illuminate\Tests\Integration\Database; | ||
|
||
use Illuminate\Foundation\Testing\RefreshDatabase; | ||
use Orchestra\Testbench\TestCase; | ||
|
||
class EloquentTransactionWithAfterCommitUsingRefreshDatabaseTest extends TestCase | ||
{ | ||
use EloquentTransactionWithAfterCommitTests; | ||
use RefreshDatabase; | ||
|
||
/** | ||
* The current database driver. | ||
* | ||
* @return string | ||
*/ | ||
protected $driver; | ||
|
||
protected function setUp(): void | ||
{ | ||
$this->beforeApplicationDestroyed(function () { | ||
foreach (array_keys($this->app['db']->getConnections()) as $name) { | ||
$this->app['db']->purge($name); | ||
} | ||
}); | ||
|
||
parent::setUp(); | ||
} | ||
|
||
protected function getEnvironmentSetUp($app) | ||
{ | ||
$connection = $app['config']->get('database.default'); | ||
|
||
$this->driver = $app['config']->get("database.connections.$connection.driver"); | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Reset
$this->transactions
after callingafterCommitCallbacksShouldBeExecuted()
so we can get the true transaction levels during the commit.