From d0ca3437e0269647c96900496d53abd271d4dfa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Sun, 29 Oct 2023 21:18:04 -0300 Subject: [PATCH 01/18] failing test --- .../Database/DatabaseTransactionsTest.php | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/Integration/Database/DatabaseTransactionsTest.php diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php new file mode 100644 index 000000000000..79e8596891ee --- /dev/null +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -0,0 +1,46 @@ + $firstObject->handle()); // Adds a callback to be executed after transaction level 2 is committed + }); + + DB::afterCommit(fn () => $secondObject->handle()); // Adds a callback to be executed after transaction 1 @ lvl 1 + + try { + DB::transaction(function () use ($thirdObject) { // Adds a transaction 3 @ level 2 + DB::afterCommit(fn () => $thirdObject->handle()); + throw new \Exception(); + }); + } catch (\Exception) {} + }); + + $this->assertTrue($firstObject->ran); + $this->assertTrue($secondObject->ran); + $this->assertFalse($thirdObject->ran); + } +} + +class TestObjectForTransactions +{ + public bool $ran = false; + + public function handle() + { + $this->ran = true; + } +} From baf3b3354008a2e3718639b3436ed2d2591be2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Sun, 29 Oct 2023 21:28:52 -0300 Subject: [PATCH 02/18] naive solution --- .../Database/Concerns/ManagesTransactions.php | 5 +++-- src/Illuminate/Database/Connection.php | 7 +++++++ src/Illuminate/Database/DatabaseTransactionRecord.php | 11 ++++++++++- .../Database/DatabaseTransactionsManager.php | 10 ++++++---- .../Integration/Database/DatabaseTransactionsTest.php | 3 +++ 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/Illuminate/Database/Concerns/ManagesTransactions.php b/src/Illuminate/Database/Concerns/ManagesTransactions.php index a690f7b5cb46..8f7dc5277b14 100644 --- a/src/Illuminate/Database/Concerns/ManagesTransactions.php +++ b/src/Illuminate/Database/Concerns/ManagesTransactions.php @@ -117,9 +117,10 @@ public function beginTransaction() $this->createTransaction(); $this->transactions++; + $this->uniqueTransactionsCounter++; $this->transactionsManager?->begin( - $this->getName(), $this->transactions + $this->getName(), $this->transactions, $this->uniqueTransactionsCounter ); $this->fireConnectionEvent('beganTransaction'); @@ -271,7 +272,7 @@ public function rollBack($toLevel = null) $this->transactions = $toLevel; $this->transactionsManager?->rollback( - $this->getName(), $this->transactions + $this->getName(), $this->transactions, $this->uniqueTransactionsCounter ); $this->fireConnectionEvent('rollingBack'); diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index a46448bb8974..ba2e3a9d27cb 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -126,6 +126,13 @@ class Connection implements ConnectionInterface */ protected $transactions = 0; + /** + * The global counter for the unique number of transactions. + * + * @var int + */ + protected $uniqueTransactionsCounter = 0; + /** * The transaction manager instance. * diff --git a/src/Illuminate/Database/DatabaseTransactionRecord.php b/src/Illuminate/Database/DatabaseTransactionRecord.php index 4736ee9224d2..d14fb5d96003 100755 --- a/src/Illuminate/Database/DatabaseTransactionRecord.php +++ b/src/Illuminate/Database/DatabaseTransactionRecord.php @@ -18,6 +18,13 @@ class DatabaseTransactionRecord */ public $level; + /** + * The transaction counter. + * + * @var int + */ + public $counter; + /** * The callbacks that should be executed after committing. * @@ -30,12 +37,14 @@ class DatabaseTransactionRecord * * @param string $connection * @param int $level + * @param int $counter * @return void */ - public function __construct($connection, $level) + public function __construct($connection, $level, $counter) { $this->connection = $connection; $this->level = $level; + $this->counter = $counter; } /** diff --git a/src/Illuminate/Database/DatabaseTransactionsManager.php b/src/Illuminate/Database/DatabaseTransactionsManager.php index e198f4f3f6d6..714b1d593fa1 100755 --- a/src/Illuminate/Database/DatabaseTransactionsManager.php +++ b/src/Illuminate/Database/DatabaseTransactionsManager.php @@ -26,12 +26,13 @@ public function __construct() * * @param string $connection * @param int $level + * @param int $counter * @return void */ - public function begin($connection, $level) + public function begin($connection, $level, $counter) { $this->transactions->push( - new DatabaseTransactionRecord($connection, $level) + new DatabaseTransactionRecord($connection, $level, $counter) ); } @@ -40,12 +41,13 @@ public function begin($connection, $level) * * @param string $connection * @param int $level + * @param int $counter * @return void */ - public function rollback($connection, $level) + public function rollback($connection, $level, $counter) { $this->transactions = $this->transactions->reject( - fn ($transaction) => $transaction->connection == $connection && $transaction->level > $level + fn ($transaction) => $transaction->connection == $connection && $transaction->level > $level && $transaction->counter === $counter )->values(); } diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index 79e8596891ee..a2a8c74cfda2 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -14,6 +14,9 @@ public function testTransactionCallbacksDoNotInterfereWithOneAnother() new TestObjectForTransactions(), ]; + // The problem here is that we're initiating a base transaction, and then two nested transactions. + // Although these two nested transactions are not the same, they share the same level (2). + // Since they are not the same, the latter one failing should not affect the first one. DB::transaction(function () use ($thirdObject, $secondObject, $firstObject) { // Adds a transaction @ level 1 DB::transaction(function () use ($firstObject) { // Adds a transaction @ level 2 DB::afterCommit(fn () => $firstObject->handle()); // Adds a callback to be executed after transaction level 2 is committed From 27d745bcb5e8c7d91361e376fb7dbfc710b63c44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Sun, 29 Oct 2023 21:30:23 -0300 Subject: [PATCH 03/18] Add comment --- tests/Integration/Database/DatabaseTransactionsTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index a2a8c74cfda2..6ea55938a7f2 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -27,7 +27,7 @@ public function testTransactionCallbacksDoNotInterfereWithOneAnother() try { DB::transaction(function () use ($thirdObject) { // Adds a transaction 3 @ level 2 DB::afterCommit(fn () => $thirdObject->handle()); - throw new \Exception(); + throw new \Exception(); // This should only affect callback 3, not 1, even though both share the same transaction level. }); } catch (\Exception) {} }); From ed7775c0f880f211c1e101c9021995dca200aba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Sun, 29 Oct 2023 21:38:05 -0300 Subject: [PATCH 04/18] Revert "naive solution" This reverts commit ef4604928c933d27280f24f082cdda13b4e8cc4c. --- .../Database/Concerns/ManagesTransactions.php | 5 ++--- src/Illuminate/Database/Connection.php | 7 ------- src/Illuminate/Database/DatabaseTransactionRecord.php | 11 +---------- .../Database/DatabaseTransactionsManager.php | 10 ++++------ .../Integration/Database/DatabaseTransactionsTest.php | 3 --- 5 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/Illuminate/Database/Concerns/ManagesTransactions.php b/src/Illuminate/Database/Concerns/ManagesTransactions.php index 8f7dc5277b14..a690f7b5cb46 100644 --- a/src/Illuminate/Database/Concerns/ManagesTransactions.php +++ b/src/Illuminate/Database/Concerns/ManagesTransactions.php @@ -117,10 +117,9 @@ public function beginTransaction() $this->createTransaction(); $this->transactions++; - $this->uniqueTransactionsCounter++; $this->transactionsManager?->begin( - $this->getName(), $this->transactions, $this->uniqueTransactionsCounter + $this->getName(), $this->transactions ); $this->fireConnectionEvent('beganTransaction'); @@ -272,7 +271,7 @@ public function rollBack($toLevel = null) $this->transactions = $toLevel; $this->transactionsManager?->rollback( - $this->getName(), $this->transactions, $this->uniqueTransactionsCounter + $this->getName(), $this->transactions ); $this->fireConnectionEvent('rollingBack'); diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index ba2e3a9d27cb..a46448bb8974 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -126,13 +126,6 @@ class Connection implements ConnectionInterface */ protected $transactions = 0; - /** - * The global counter for the unique number of transactions. - * - * @var int - */ - protected $uniqueTransactionsCounter = 0; - /** * The transaction manager instance. * diff --git a/src/Illuminate/Database/DatabaseTransactionRecord.php b/src/Illuminate/Database/DatabaseTransactionRecord.php index d14fb5d96003..4736ee9224d2 100755 --- a/src/Illuminate/Database/DatabaseTransactionRecord.php +++ b/src/Illuminate/Database/DatabaseTransactionRecord.php @@ -18,13 +18,6 @@ class DatabaseTransactionRecord */ public $level; - /** - * The transaction counter. - * - * @var int - */ - public $counter; - /** * The callbacks that should be executed after committing. * @@ -37,14 +30,12 @@ class DatabaseTransactionRecord * * @param string $connection * @param int $level - * @param int $counter * @return void */ - public function __construct($connection, $level, $counter) + public function __construct($connection, $level) { $this->connection = $connection; $this->level = $level; - $this->counter = $counter; } /** diff --git a/src/Illuminate/Database/DatabaseTransactionsManager.php b/src/Illuminate/Database/DatabaseTransactionsManager.php index 714b1d593fa1..e198f4f3f6d6 100755 --- a/src/Illuminate/Database/DatabaseTransactionsManager.php +++ b/src/Illuminate/Database/DatabaseTransactionsManager.php @@ -26,13 +26,12 @@ public function __construct() * * @param string $connection * @param int $level - * @param int $counter * @return void */ - public function begin($connection, $level, $counter) + public function begin($connection, $level) { $this->transactions->push( - new DatabaseTransactionRecord($connection, $level, $counter) + new DatabaseTransactionRecord($connection, $level) ); } @@ -41,13 +40,12 @@ public function begin($connection, $level, $counter) * * @param string $connection * @param int $level - * @param int $counter * @return void */ - public function rollback($connection, $level, $counter) + public function rollback($connection, $level) { $this->transactions = $this->transactions->reject( - fn ($transaction) => $transaction->connection == $connection && $transaction->level > $level && $transaction->counter === $counter + fn ($transaction) => $transaction->connection == $connection && $transaction->level > $level )->values(); } diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index 6ea55938a7f2..cbabbdb8c978 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -14,9 +14,6 @@ public function testTransactionCallbacksDoNotInterfereWithOneAnother() new TestObjectForTransactions(), ]; - // The problem here is that we're initiating a base transaction, and then two nested transactions. - // Although these two nested transactions are not the same, they share the same level (2). - // Since they are not the same, the latter one failing should not affect the first one. DB::transaction(function () use ($thirdObject, $secondObject, $firstObject) { // Adds a transaction @ level 1 DB::transaction(function () use ($firstObject) { // Adds a transaction @ level 2 DB::afterCommit(fn () => $firstObject->handle()); // Adds a callback to be executed after transaction level 2 is committed From 5cb5f61df9a8c503c3575b97557a396b806dc061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Sun, 29 Oct 2023 22:33:17 -0300 Subject: [PATCH 05/18] wip --- .../Database/Concerns/ManagesTransactions.php | 4 ++ .../Database/DatabaseTransactionsManager.php | 40 ++++++++++++++----- .../Database/DatabaseTransactionsTest.php | 3 ++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/Illuminate/Database/Concerns/ManagesTransactions.php b/src/Illuminate/Database/Concerns/ManagesTransactions.php index a690f7b5cb46..3b553c45488e 100644 --- a/src/Illuminate/Database/Concerns/ManagesTransactions.php +++ b/src/Illuminate/Database/Concerns/ManagesTransactions.php @@ -47,6 +47,8 @@ public function transaction(Closure $callback, $attempts = 1) $this->getPdo()->commit(); } + $this->transactionsManager->stageTransactions(); + $this->transactions = max(0, $this->transactions - 1); if ($this->afterCommitCallbacksShouldBeExecuted()) { @@ -194,6 +196,8 @@ public function commit() $this->getPdo()->commit(); } + $this->transactionsManager?->stageTransactions(); + $this->transactions = max(0, $this->transactions - 1); if ($this->afterCommitCallbacksShouldBeExecuted()) { diff --git a/src/Illuminate/Database/DatabaseTransactionsManager.php b/src/Illuminate/Database/DatabaseTransactionsManager.php index e198f4f3f6d6..8df81b2cbde3 100755 --- a/src/Illuminate/Database/DatabaseTransactionsManager.php +++ b/src/Illuminate/Database/DatabaseTransactionsManager.php @@ -5,11 +5,18 @@ class DatabaseTransactionsManager { /** - * All of the recorded transactions. + * All of the recorded ready transactions. * * @var \Illuminate\Support\Collection */ - protected $transactions; + protected $readyTransactions; + + /** + * All of the recorded pending transactions. + * + * @var \Illuminate\Support\Collection + */ + protected $pendingTransactions; /** * Create a new database transactions manager instance. @@ -18,7 +25,8 @@ class DatabaseTransactionsManager */ public function __construct() { - $this->transactions = collect(); + $this->readyTransactions = collect(); + $this->pendingTransactions = collect(); } /** @@ -30,7 +38,7 @@ public function __construct() */ public function begin($connection, $level) { - $this->transactions->push( + $this->pendingTransactions->push( new DatabaseTransactionRecord($connection, $level) ); } @@ -44,7 +52,7 @@ public function begin($connection, $level) */ public function rollback($connection, $level) { - $this->transactions = $this->transactions->reject( + $this->pendingTransactions = $this->pendingTransactions->reject( fn ($transaction) => $transaction->connection == $connection && $transaction->level > $level )->values(); } @@ -57,11 +65,11 @@ public function rollback($connection, $level) */ public function commit($connection) { - [$forThisConnection, $forOtherConnections] = $this->transactions->partition( + [$forThisConnection, $forOtherConnections] = $this->readyTransactions->partition( fn ($transaction) => $transaction->connection == $connection ); - $this->transactions = $forOtherConnections->values(); + $this->readyTransactions = $forOtherConnections->values(); $forThisConnection->map->executeCallbacks(); } @@ -81,6 +89,20 @@ public function addCallback($callback) $callback(); } + /** + * Move all the pending transactions to a ready state. + * + * @return void + */ + public function stageTransactions() + { + $this->readyTransactions = $this->readyTransactions->merge( + $this->pendingTransactions + ); + + $this->pendingTransactions = collect(); + } + /** * Get the transactions that are applicable to callbacks. * @@ -88,7 +110,7 @@ public function addCallback($callback) */ public function callbackApplicableTransactions() { - return $this->transactions; + return $this->pendingTransactions; } /** @@ -109,6 +131,6 @@ public function afterCommitCallbacksShouldBeExecuted($level) */ public function getTransactions() { - return $this->transactions; + return $this->readyTransactions; } } diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index cbabbdb8c978..6ea55938a7f2 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -14,6 +14,9 @@ public function testTransactionCallbacksDoNotInterfereWithOneAnother() new TestObjectForTransactions(), ]; + // The problem here is that we're initiating a base transaction, and then two nested transactions. + // Although these two nested transactions are not the same, they share the same level (2). + // Since they are not the same, the latter one failing should not affect the first one. DB::transaction(function () use ($thirdObject, $secondObject, $firstObject) { // Adds a transaction @ level 1 DB::transaction(function () use ($firstObject) { // Adds a transaction @ level 2 DB::afterCommit(fn () => $firstObject->handle()); // Adds a callback to be executed after transaction level 2 is committed From de0596494793a147f714db27121b4c6f75265e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Sun, 29 Oct 2023 22:48:25 -0300 Subject: [PATCH 06/18] Fix DatabaseTransactionsManager tests --- .../Database/DatabaseTransactionsManager.php | 14 +++++- .../DatabaseTransactionsManagerTest.php | 46 ++++++++++--------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/Illuminate/Database/DatabaseTransactionsManager.php b/src/Illuminate/Database/DatabaseTransactionsManager.php index 8df81b2cbde3..448b8caa4b84 100755 --- a/src/Illuminate/Database/DatabaseTransactionsManager.php +++ b/src/Illuminate/Database/DatabaseTransactionsManager.php @@ -125,11 +125,21 @@ public function afterCommitCallbacksShouldBeExecuted($level) } /** - * Get all the transactions. + * Get all the pending transactions. * * @return \Illuminate\Support\Collection */ - public function getTransactions() + public function getPendingTransactions() + { + return $this->pendingTransactions; + } + + /** + * Get all the ready transactions. + * + * @return \Illuminate\Support\Collection + */ + public function getReadyTransactions() { return $this->readyTransactions; } diff --git a/tests/Database/DatabaseTransactionsManagerTest.php b/tests/Database/DatabaseTransactionsManagerTest.php index e8d82e048720..e75961c0f788 100755 --- a/tests/Database/DatabaseTransactionsManagerTest.php +++ b/tests/Database/DatabaseTransactionsManagerTest.php @@ -15,13 +15,13 @@ public function testBeginningTransactions() $manager->begin('default', 2); $manager->begin('admin', 1); - $this->assertCount(3, $manager->getTransactions()); - $this->assertSame('default', $manager->getTransactions()[0]->connection); - $this->assertEquals(1, $manager->getTransactions()[0]->level); - $this->assertSame('default', $manager->getTransactions()[1]->connection); - $this->assertEquals(2, $manager->getTransactions()[1]->level); - $this->assertSame('admin', $manager->getTransactions()[2]->connection); - $this->assertEquals(1, $manager->getTransactions()[2]->level); + $this->assertCount(3, $manager->getPendingTransactions()); + $this->assertSame('default', $manager->getPendingTransactions()[0]->connection); + $this->assertEquals(1, $manager->getPendingTransactions()[0]->level); + $this->assertSame('default', $manager->getPendingTransactions()[1]->connection); + $this->assertEquals(2, $manager->getPendingTransactions()[1]->level); + $this->assertSame('admin', $manager->getPendingTransactions()[2]->connection); + $this->assertEquals(1, $manager->getPendingTransactions()[2]->level); } public function testRollingBackTransactions() @@ -34,13 +34,13 @@ public function testRollingBackTransactions() $manager->rollback('default', 1); - $this->assertCount(2, $manager->getTransactions()); + $this->assertCount(2, $manager->getPendingTransactions()); - $this->assertSame('default', $manager->getTransactions()[0]->connection); - $this->assertEquals(1, $manager->getTransactions()[0]->level); + $this->assertSame('default', $manager->getPendingTransactions()[0]->connection); + $this->assertEquals(1, $manager->getPendingTransactions()[0]->level); - $this->assertSame('admin', $manager->getTransactions()[1]->connection); - $this->assertEquals(1, $manager->getTransactions()[1]->level); + $this->assertSame('admin', $manager->getPendingTransactions()[1]->connection); + $this->assertEquals(1, $manager->getPendingTransactions()[1]->level); } public function testRollingBackTransactionsAllTheWay() @@ -53,10 +53,10 @@ public function testRollingBackTransactionsAllTheWay() $manager->rollback('default', 0); - $this->assertCount(1, $manager->getTransactions()); + $this->assertCount(1, $manager->getPendingTransactions()); - $this->assertSame('admin', $manager->getTransactions()[0]->connection); - $this->assertEquals(1, $manager->getTransactions()[0]->level); + $this->assertSame('admin', $manager->getPendingTransactions()[0]->connection); + $this->assertEquals(1, $manager->getPendingTransactions()[0]->level); } public function testCommittingTransactions() @@ -67,12 +67,14 @@ public function testCommittingTransactions() $manager->begin('default', 2); $manager->begin('admin', 1); + $manager->stageTransactions(); $manager->commit('default'); - $this->assertCount(1, $manager->getTransactions()); + $this->assertCount(0, $manager->getPendingTransactions()); + $this->assertCount(1, $manager->getReadyTransactions()); - $this->assertSame('admin', $manager->getTransactions()[0]->connection); - $this->assertEquals(1, $manager->getTransactions()[0]->level); + $this->assertSame('admin', $manager->getReadyTransactions()[0]->connection); + $this->assertEquals(1, $manager->getReadyTransactions()[0]->level); } public function testCallbacksAreAddedToTheCurrentTransaction() @@ -93,9 +95,9 @@ public function testCallbacksAreAddedToTheCurrentTransaction() $manager->addCallback(function () use (&$callbacks) { }); - $this->assertCount(1, $manager->getTransactions()[0]->getCallbacks()); - $this->assertCount(0, $manager->getTransactions()[1]->getCallbacks()); - $this->assertCount(1, $manager->getTransactions()[2]->getCallbacks()); + $this->assertCount(1, $manager->getPendingTransactions()[0]->getCallbacks()); + $this->assertCount(0, $manager->getPendingTransactions()[1]->getCallbacks()); + $this->assertCount(1, $manager->getPendingTransactions()[2]->getCallbacks()); } public function testCommittingTransactionsExecutesCallbacks() @@ -118,6 +120,7 @@ public function testCommittingTransactionsExecutesCallbacks() $manager->begin('admin', 1); + $manager->stageTransactions(); $manager->commit('default'); $this->assertCount(2, $callbacks); @@ -144,6 +147,7 @@ public function testCommittingExecutesOnlyCallbacksOfTheConnection() $callbacks[] = ['admin', 1]; }); + $manager->stageTransactions(); $manager->commit('default'); $this->assertCount(1, $callbacks); From 685436509484cca92bfcbc591427e18e2e474cfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Sun, 29 Oct 2023 22:48:50 -0300 Subject: [PATCH 07/18] fix null object --- src/Illuminate/Database/Concerns/ManagesTransactions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Concerns/ManagesTransactions.php b/src/Illuminate/Database/Concerns/ManagesTransactions.php index 3b553c45488e..3c0bab260f95 100644 --- a/src/Illuminate/Database/Concerns/ManagesTransactions.php +++ b/src/Illuminate/Database/Concerns/ManagesTransactions.php @@ -47,7 +47,7 @@ public function transaction(Closure $callback, $attempts = 1) $this->getPdo()->commit(); } - $this->transactionsManager->stageTransactions(); + $this->transactionsManager?->stageTransactions(); $this->transactions = max(0, $this->transactions - 1); From 3efe6a1a776809c01620926ec43929385523aebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Sun, 29 Oct 2023 22:55:42 -0300 Subject: [PATCH 08/18] Fix Testing DatabaseTransactionsManager --- .../Foundation/Testing/DatabaseTransactionsManager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Foundation/Testing/DatabaseTransactionsManager.php b/src/Illuminate/Foundation/Testing/DatabaseTransactionsManager.php index 08c1635443a6..bc5450486d48 100644 --- a/src/Illuminate/Foundation/Testing/DatabaseTransactionsManager.php +++ b/src/Illuminate/Foundation/Testing/DatabaseTransactionsManager.php @@ -21,7 +21,7 @@ public function addCallback($callback) return $callback(); } - $this->transactions->last()->addCallback($callback); + $this->pendingTransactions->last()->addCallback($callback); } /** @@ -31,7 +31,7 @@ public function addCallback($callback) */ public function callbackApplicableTransactions() { - return $this->transactions->skip(1)->values(); + return $this->pendingTransactions->skip(1)->values(); } /** From b2375760c274f138cd68c8f0eb9d10902b550640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Sun, 29 Oct 2023 22:56:26 -0300 Subject: [PATCH 09/18] make styleci happy --- tests/Integration/Database/DatabaseTransactionsTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index 6ea55938a7f2..20b3d6213097 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -29,7 +29,8 @@ public function testTransactionCallbacksDoNotInterfereWithOneAnother() DB::afterCommit(fn () => $thirdObject->handle()); throw new \Exception(); // This should only affect callback 3, not 1, even though both share the same transaction level. }); - } catch (\Exception) {} + } catch (\Exception) { + } }); $this->assertTrue($firstObject->ran); From a4b2d4ccddbacc2566681de21eb959d28fa2b972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Wed, 1 Nov 2023 15:51:11 -0300 Subject: [PATCH 10/18] additional test --- .../Database/DatabaseTransactionsTest.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index 20b3d6213097..7dca5d642d0b 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -6,6 +6,27 @@ class DatabaseTransactionsTest extends DatabaseTestCase { + public function testTransactionCallbacks() + { + [$firstObject, $secondObject, $thirdObject] = [ + new TestObjectForTransactions(), + new TestObjectForTransactions(), + new TestObjectForTransactions() + ]; + + DB::transaction(function () use ($secondObject, $firstObject) { + DB::afterCommit(fn () => $firstObject->handle()); + + DB::transaction(function () use ($secondObject) { + DB::afterCommit(fn () => $secondObject->handle()); + }); + }); + + $this->assertTrue($firstObject->ran); + $this->assertTrue($secondObject->ran); + $this->assertFalse($thirdObject->ran); + } + public function testTransactionCallbacksDoNotInterfereWithOneAnother() { [$firstObject, $secondObject, $thirdObject] = [ From abd8c81212b11aa08ce69301b07dacfaf1682531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Wed, 1 Nov 2023 17:19:00 -0300 Subject: [PATCH 11/18] Pass connection name to stageTransactions --- .../Database/Concerns/ManagesTransactions.php | 4 +- .../Database/DatabaseTransactionsManager.php | 7 ++- .../DatabaseTransactionsManagerTest.php | 7 ++- tests/Database/DatabaseTransactionsTest.php | 5 ++ .../Database/DatabaseTransactionsTest.php | 59 ++++++++++++++++++- 5 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/Illuminate/Database/Concerns/ManagesTransactions.php b/src/Illuminate/Database/Concerns/ManagesTransactions.php index 3c0bab260f95..0f6aa0239a71 100644 --- a/src/Illuminate/Database/Concerns/ManagesTransactions.php +++ b/src/Illuminate/Database/Concerns/ManagesTransactions.php @@ -47,7 +47,7 @@ public function transaction(Closure $callback, $attempts = 1) $this->getPdo()->commit(); } - $this->transactionsManager?->stageTransactions(); + $this->transactionsManager?->stageTransactions($this->getName()); $this->transactions = max(0, $this->transactions - 1); @@ -196,7 +196,7 @@ public function commit() $this->getPdo()->commit(); } - $this->transactionsManager?->stageTransactions(); + $this->transactionsManager?->stageTransactions($this->getName()); $this->transactions = max(0, $this->transactions - 1); diff --git a/src/Illuminate/Database/DatabaseTransactionsManager.php b/src/Illuminate/Database/DatabaseTransactionsManager.php index 448b8caa4b84..3f0b1bd2529b 100755 --- a/src/Illuminate/Database/DatabaseTransactionsManager.php +++ b/src/Illuminate/Database/DatabaseTransactionsManager.php @@ -92,15 +92,16 @@ public function addCallback($callback) /** * Move all the pending transactions to a ready state. * + * @param string $connection * @return void */ - public function stageTransactions() + public function stageTransactions($connection) { $this->readyTransactions = $this->readyTransactions->merge( - $this->pendingTransactions + $this->pendingTransactions->filter(fn ($transaction) => $transaction->connection === $connection) ); - $this->pendingTransactions = collect(); + $this->pendingTransactions = $this->pendingTransactions->reject(fn ($transaction) => $transaction->connection === $connection); } /** diff --git a/tests/Database/DatabaseTransactionsManagerTest.php b/tests/Database/DatabaseTransactionsManagerTest.php index e75961c0f788..cab0a4215671 100755 --- a/tests/Database/DatabaseTransactionsManagerTest.php +++ b/tests/Database/DatabaseTransactionsManagerTest.php @@ -67,7 +67,8 @@ public function testCommittingTransactions() $manager->begin('default', 2); $manager->begin('admin', 1); - $manager->stageTransactions(); + $manager->stageTransactions('default'); + $manager->stageTransactions('admin'); $manager->commit('default'); $this->assertCount(0, $manager->getPendingTransactions()); @@ -120,7 +121,7 @@ public function testCommittingTransactionsExecutesCallbacks() $manager->begin('admin', 1); - $manager->stageTransactions(); + $manager->stageTransactions('default'); $manager->commit('default'); $this->assertCount(2, $callbacks); @@ -147,7 +148,7 @@ public function testCommittingExecutesOnlyCallbacksOfTheConnection() $callbacks[] = ['admin', 1]; }); - $manager->stageTransactions(); + $manager->stageTransactions('default'); $manager->commit('default'); $this->assertCount(1, $callbacks); diff --git a/tests/Database/DatabaseTransactionsTest.php b/tests/Database/DatabaseTransactionsTest.php index ac9587419eeb..94998f010c01 100644 --- a/tests/Database/DatabaseTransactionsTest.php +++ b/tests/Database/DatabaseTransactionsTest.php @@ -64,6 +64,7 @@ public function testTransactionIsRecordedAndCommitted() { $transactionManager = m::mock(new DatabaseTransactionsManager); $transactionManager->shouldReceive('begin')->once()->with('default', 1); + $transactionManager->shouldReceive('stageTransactions')->once()->with('default'); $transactionManager->shouldReceive('commit')->once()->with('default'); $this->connection()->setTransactionManager($transactionManager); @@ -83,6 +84,7 @@ public function testTransactionIsRecordedAndCommittedUsingTheSeparateMethods() { $transactionManager = m::mock(new DatabaseTransactionsManager); $transactionManager->shouldReceive('begin')->once()->with('default', 1); + $transactionManager->shouldReceive('stageTransactions')->once()->with('default'); $transactionManager->shouldReceive('commit')->once()->with('default'); $this->connection()->setTransactionManager($transactionManager); @@ -103,6 +105,7 @@ public function testNestedTransactionIsRecordedAndCommitted() $transactionManager = m::mock(new DatabaseTransactionsManager); $transactionManager->shouldReceive('begin')->once()->with('default', 1); $transactionManager->shouldReceive('begin')->once()->with('default', 2); + $transactionManager->shouldReceive('stageTransactions')->twice()->with('default'); $transactionManager->shouldReceive('commit')->once()->with('default'); $this->connection()->setTransactionManager($transactionManager); @@ -130,6 +133,8 @@ public function testNestedTransactionIsRecordeForDifferentConnectionsdAndCommitt $transactionManager->shouldReceive('begin')->once()->with('default', 1); $transactionManager->shouldReceive('begin')->once()->with('second_connection', 1); $transactionManager->shouldReceive('begin')->once()->with('second_connection', 2); + $transactionManager->shouldReceive('stageTransactions')->once()->with('default'); + $transactionManager->shouldReceive('stageTransactions')->twice()->with('second_connection'); $transactionManager->shouldReceive('commit')->once()->with('default'); $transactionManager->shouldReceive('commit')->once()->with('second_connection'); diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index 7dca5d642d0b..10dde257d734 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -3,9 +3,28 @@ namespace Illuminate\Tests\Integration\Database; use Illuminate\Support\Facades\DB; +use Illuminate\Database\Capsule\Manager; +use Orchestra\Testbench\TestCase; -class DatabaseTransactionsTest extends DatabaseTestCase +class DatabaseTransactionsTest extends TestCase { + protected function setUp(): void + { + parent::setUp(); + + app(Manager::class) + ->addConnection([ + 'driver' => 'sqlite', + 'database' => ':memory:', + ]); + + app(Manager::class) + ->addConnection([ + 'driver' => 'sqlite', + 'database' => ':memory:', + ], 'second_connection'); + } + public function testTransactionCallbacks() { [$firstObject, $secondObject, $thirdObject] = [ @@ -24,6 +43,8 @@ public function testTransactionCallbacks() $this->assertTrue($firstObject->ran); $this->assertTrue($secondObject->ran); + $this->assertEquals(1, $firstObject->runs); + $this->assertEquals(1, $secondObject->runs); $this->assertFalse($thirdObject->ran); } @@ -54,6 +75,37 @@ public function testTransactionCallbacksDoNotInterfereWithOneAnother() } }); + $this->assertTrue($firstObject->ran); + $this->assertTrue($secondObject->ran); + $this->assertEquals(1, $firstObject->runs); + $this->assertEquals(1, $secondObject->runs); + $this->assertFalse($thirdObject->ran); + } + + public function testTransactionsDoNotAffectDifferentConnections() + { + [$firstObject, $secondObject, $thirdObject] = [ + new TestObjectForTransactions(), + new TestObjectForTransactions(), + new TestObjectForTransactions() + ]; + + DB::transaction(function () use ($secondObject, $firstObject, $thirdObject) { + DB::transaction(function () use ($secondObject) { + DB::afterCommit(fn () => $secondObject->handle()); + }); + + DB::afterCommit(fn () => $firstObject->handle()); + + try { + DB::connection('second_connection')->transaction(function () use ($thirdObject) { + DB::afterCommit(fn() => $thirdObject->handle()); + + throw new \Exception; + }); + } catch (\Exception) {} + }); + $this->assertTrue($firstObject->ran); $this->assertTrue($secondObject->ran); $this->assertFalse($thirdObject->ran); @@ -62,10 +114,13 @@ public function testTransactionCallbacksDoNotInterfereWithOneAnother() class TestObjectForTransactions { - public bool $ran = false; + public $ran = false; + + public $runs = 0; public function handle() { $this->ran = true; + $this->runs++; } } From 0f72c8b6177546b004211a61c58af8eb9edd2f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Thu, 2 Nov 2023 12:29:00 -0300 Subject: [PATCH 12/18] Add unit test --- .../DatabaseTransactionsManagerTest.php | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/Database/DatabaseTransactionsManagerTest.php b/tests/Database/DatabaseTransactionsManagerTest.php index cab0a4215671..eeaeb2624261 100755 --- a/tests/Database/DatabaseTransactionsManagerTest.php +++ b/tests/Database/DatabaseTransactionsManagerTest.php @@ -168,4 +168,33 @@ public function testCallbackIsExecutedIfNoTransactions() $this->assertCount(1, $callbacks); $this->assertEquals(['default', 1], $callbacks[0]); } + + public function testStageTransactions() + { + $manager = (new DatabaseTransactionsManager); + + $manager->begin('default', 1); + $manager->begin('admin', 1); + + $this->assertCount(2, $manager->getPendingTransactions()); + + $pendingTransactions = $manager->getPendingTransactions(); + + $this->assertEquals(1, $pendingTransactions[0]->level); + $this->assertEquals('default', $pendingTransactions[0]->connection); + $this->assertEquals(1, $pendingTransactions[1]->level); + $this->assertEquals('admin', $pendingTransactions[1]->connection); + + $manager->stageTransactions('default'); + + $this->assertCount(1, $manager->getPendingTransactions()); + $this->assertCount(1, $manager->getReadyTransactions()); + $this->assertEquals('default', $manager->getReadyTransactions()[0]->connection); + + $manager->stageTransactions('admin'); + + $this->assertCount(0, $manager->getPendingTransactions()); + $this->assertCount(2, $manager->getReadyTransactions()); + $this->assertEquals('admin', $manager->getReadyTransactions()[1]->connection); + } } From 5d30f1aefa6f88c8eb2605f21f249dc7380c1a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateus=20Guimar=C3=A3es?= Date: Thu, 2 Nov 2023 12:43:48 -0300 Subject: [PATCH 13/18] add tests for Testing DatabaseTransactionsManager --- .../DatabaseTransactionsManagerTest.php | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 tests/Foundation/Testing/DatabaseTransactionsManagerTest.php diff --git a/tests/Foundation/Testing/DatabaseTransactionsManagerTest.php b/tests/Foundation/Testing/DatabaseTransactionsManagerTest.php new file mode 100644 index 000000000000..b0add2e650eb --- /dev/null +++ b/tests/Foundation/Testing/DatabaseTransactionsManagerTest.php @@ -0,0 +1,71 @@ +begin('foo', 1); + + $manager->addCallback(fn () => $testObject->handle()); + + $this->assertTrue($testObject->ran); + $this->assertEquals(1, $testObject->runs); + } + + public function testItIgnoresTheBaseTransactionForCallbackApplicableTransactions() + { + $manager = new DatabaseTransactionsManager; + + $manager->begin('foo', 1); + $manager->begin('foo', 2); + + $this->assertCount(1, $manager->callbackApplicableTransactions()); + $this->assertEquals(2, $manager->callbackApplicableTransactions()[0]->level); + } + + public function testItExecutesCallbacksForTheSecondTransaction() + { + $testObject = new TestingDatabaseTransactionsManagerTestObject(); + $manager = new DatabaseTransactionsManager; + $manager->begin('foo', 1); + $manager->begin('foo', 2); + + $manager->addCallback(fn () => $testObject->handle()); + + $this->assertFalse($testObject->ran); + + $manager->stageTransactions('foo'); + $manager->commit('foo'); + $this->assertTrue($testObject->ran); + $this->assertEquals(1, $testObject->runs); + } + + public function testItExecutesTransactionCallbacksAtLevelOne() + { + $manager = new DatabaseTransactionsManager; + + $this->assertFalse($manager->afterCommitCallbacksShouldBeExecuted(0)); + $this->assertTrue($manager->afterCommitCallbacksShouldBeExecuted(1)); + $this->assertFalse($manager->afterCommitCallbacksShouldBeExecuted(2)); + } +} + +class TestingDatabaseTransactionsManagerTestObject +{ + public $ran = false; + public $runs = 0; + + public function handle() + { + $this->ran = true; + $this->runs++; + } +} From dba93f369fcb374474548390fb54dc15ec434200 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Thu, 9 Nov 2023 09:06:00 +0800 Subject: [PATCH 14/18] wip Signed-off-by: Mior Muhammad Zaki --- .../Database/DatabaseTransactionsTest.php | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index 10dde257d734..b621cc4d0835 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -8,21 +8,15 @@ class DatabaseTransactionsTest extends TestCase { - protected function setUp(): void + protected function defineEnvironment($app) { - parent::setUp(); - - app(Manager::class) - ->addConnection([ - 'driver' => 'sqlite', - 'database' => ':memory:', - ]); - - app(Manager::class) - ->addConnection([ + $app['config']->set([ + 'database.default' => 'testing', + 'database.connections.second_connection' => [ 'driver' => 'sqlite', 'database' => ':memory:', - ], 'second_connection'); + ], + ]); } public function testTransactionCallbacks() From ff85ee0c48009a3de91a3f7bb92d2d8d76a64a4b Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Thu, 9 Nov 2023 09:06:41 +0800 Subject: [PATCH 15/18] wip Signed-off-by: Mior Muhammad Zaki --- tests/Integration/Database/DatabaseTransactionsTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index b621cc4d0835..1146476f64f3 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -3,7 +3,6 @@ namespace Illuminate\Tests\Integration\Database; use Illuminate\Support\Facades\DB; -use Illuminate\Database\Capsule\Manager; use Orchestra\Testbench\TestCase; class DatabaseTransactionsTest extends TestCase From 42e6f25c82893b85d059fbc053db7143985e21d1 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Thu, 9 Nov 2023 09:12:30 +0800 Subject: [PATCH 16/18] wip Signed-off-by: Mior Muhammad Zaki --- .../Database/DatabaseTransactionsManager.php | 2 +- .../Integration/Database/DatabaseTransactionsTest.php | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Database/DatabaseTransactionsManager.php b/src/Illuminate/Database/DatabaseTransactionsManager.php index 3f0b1bd2529b..c95b6c569da5 100755 --- a/src/Illuminate/Database/DatabaseTransactionsManager.php +++ b/src/Illuminate/Database/DatabaseTransactionsManager.php @@ -92,7 +92,7 @@ public function addCallback($callback) /** * Move all the pending transactions to a ready state. * - * @param string $connection + * @param string $connection * @return void */ public function stageTransactions($connection) diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index 1146476f64f3..6eaaec5af3a1 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -23,7 +23,7 @@ public function testTransactionCallbacks() [$firstObject, $secondObject, $thirdObject] = [ new TestObjectForTransactions(), new TestObjectForTransactions(), - new TestObjectForTransactions() + new TestObjectForTransactions(), ]; DB::transaction(function () use ($secondObject, $firstObject) { @@ -80,7 +80,7 @@ public function testTransactionsDoNotAffectDifferentConnections() [$firstObject, $secondObject, $thirdObject] = [ new TestObjectForTransactions(), new TestObjectForTransactions(), - new TestObjectForTransactions() + new TestObjectForTransactions(), ]; DB::transaction(function () use ($secondObject, $firstObject, $thirdObject) { @@ -92,11 +92,13 @@ public function testTransactionsDoNotAffectDifferentConnections() try { DB::connection('second_connection')->transaction(function () use ($thirdObject) { - DB::afterCommit(fn() => $thirdObject->handle()); + DB::afterCommit(fn () => $thirdObject->handle()); throw new \Exception; }); - } catch (\Exception) {} + } catch (\Exception) { + // + } }); $this->assertTrue($firstObject->ran); From 74bdc621a5a6e33c9c8518ab94514cb02ac8d826 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Thu, 9 Nov 2023 10:35:58 +0800 Subject: [PATCH 17/18] wip Signed-off-by: Mior Muhammad Zaki --- tests/Integration/Database/DatabaseTransactionsTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Integration/Database/DatabaseTransactionsTest.php b/tests/Integration/Database/DatabaseTransactionsTest.php index 6eaaec5af3a1..58894d01ae5e 100644 --- a/tests/Integration/Database/DatabaseTransactionsTest.php +++ b/tests/Integration/Database/DatabaseTransactionsTest.php @@ -3,14 +3,14 @@ namespace Illuminate\Tests\Integration\Database; use Illuminate\Support\Facades\DB; -use Orchestra\Testbench\TestCase; -class DatabaseTransactionsTest extends TestCase +class DatabaseTransactionsTest extends DatabaseTestCase { protected function defineEnvironment($app) { + parent::defineEnvironment($app); + $app['config']->set([ - 'database.default' => 'testing', 'database.connections.second_connection' => [ 'driver' => 'sqlite', 'database' => ':memory:', From 21792d1c9af2a87903c4728306bad54a962f201e Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 10 Nov 2023 13:38:46 -0600 Subject: [PATCH 18/18] formatting --- .../Database/DatabaseTransactionsManager.php | 32 +++++++++++-------- .../DatabaseTransactionsManagerTest.php | 14 ++++---- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/Illuminate/Database/DatabaseTransactionsManager.php b/src/Illuminate/Database/DatabaseTransactionsManager.php index c95b6c569da5..2914464858e6 100755 --- a/src/Illuminate/Database/DatabaseTransactionsManager.php +++ b/src/Illuminate/Database/DatabaseTransactionsManager.php @@ -2,17 +2,19 @@ namespace Illuminate\Database; +use Illuminate\Support\Collection; + class DatabaseTransactionsManager { /** - * All of the recorded ready transactions. + * All of the committed transactions. * * @var \Illuminate\Support\Collection */ - protected $readyTransactions; + protected $committedTransactions; /** - * All of the recorded pending transactions. + * All of the pending transactions. * * @var \Illuminate\Support\Collection */ @@ -25,8 +27,8 @@ class DatabaseTransactionsManager */ public function __construct() { - $this->readyTransactions = collect(); - $this->pendingTransactions = collect(); + $this->committedTransactions = new Collection; + $this->pendingTransactions = new Collection; } /** @@ -65,11 +67,11 @@ public function rollback($connection, $level) */ public function commit($connection) { - [$forThisConnection, $forOtherConnections] = $this->readyTransactions->partition( + [$forThisConnection, $forOtherConnections] = $this->committedTransactions->partition( fn ($transaction) => $transaction->connection == $connection ); - $this->readyTransactions = $forOtherConnections->values(); + $this->committedTransactions = $forOtherConnections->values(); $forThisConnection->map->executeCallbacks(); } @@ -90,18 +92,20 @@ public function addCallback($callback) } /** - * Move all the pending transactions to a ready state. + * Move all the pending transactions to a committed state. * * @param string $connection * @return void */ public function stageTransactions($connection) { - $this->readyTransactions = $this->readyTransactions->merge( + $this->committedTransactions = $this->committedTransactions->merge( $this->pendingTransactions->filter(fn ($transaction) => $transaction->connection === $connection) ); - $this->pendingTransactions = $this->pendingTransactions->reject(fn ($transaction) => $transaction->connection === $connection); + $this->pendingTransactions = $this->pendingTransactions->reject( + fn ($transaction) => $transaction->connection === $connection + ); } /** @@ -126,7 +130,7 @@ public function afterCommitCallbacksShouldBeExecuted($level) } /** - * Get all the pending transactions. + * Get all of the pending transactions. * * @return \Illuminate\Support\Collection */ @@ -136,12 +140,12 @@ public function getPendingTransactions() } /** - * Get all the ready transactions. + * Get all of the committed transactions. * * @return \Illuminate\Support\Collection */ - public function getReadyTransactions() + public function getCommittedTransactions() { - return $this->readyTransactions; + return $this->committedTransactions; } } diff --git a/tests/Database/DatabaseTransactionsManagerTest.php b/tests/Database/DatabaseTransactionsManagerTest.php index eeaeb2624261..e303b82d89cd 100755 --- a/tests/Database/DatabaseTransactionsManagerTest.php +++ b/tests/Database/DatabaseTransactionsManagerTest.php @@ -72,10 +72,10 @@ public function testCommittingTransactions() $manager->commit('default'); $this->assertCount(0, $manager->getPendingTransactions()); - $this->assertCount(1, $manager->getReadyTransactions()); + $this->assertCount(1, $manager->getCommittedTransactions()); - $this->assertSame('admin', $manager->getReadyTransactions()[0]->connection); - $this->assertEquals(1, $manager->getReadyTransactions()[0]->level); + $this->assertSame('admin', $manager->getCommittedTransactions()[0]->connection); + $this->assertEquals(1, $manager->getCommittedTransactions()[0]->level); } public function testCallbacksAreAddedToTheCurrentTransaction() @@ -188,13 +188,13 @@ public function testStageTransactions() $manager->stageTransactions('default'); $this->assertCount(1, $manager->getPendingTransactions()); - $this->assertCount(1, $manager->getReadyTransactions()); - $this->assertEquals('default', $manager->getReadyTransactions()[0]->connection); + $this->assertCount(1, $manager->getCommittedTransactions()); + $this->assertEquals('default', $manager->getCommittedTransactions()[0]->connection); $manager->stageTransactions('admin'); $this->assertCount(0, $manager->getPendingTransactions()); - $this->assertCount(2, $manager->getReadyTransactions()); - $this->assertEquals('admin', $manager->getReadyTransactions()[1]->connection); + $this->assertCount(2, $manager->getCommittedTransactions()); + $this->assertEquals('admin', $manager->getCommittedTransactions()[1]->connection); } }