From 5535c6b4eb9e3217d974c41fb3f159d7498598ef Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Wed, 25 Nov 2020 17:13:24 +0200 Subject: [PATCH 1/7] transactions manager --- .../Database/DatabaseTransactionRecord.php | 73 ++++++++ .../Database/DatabaseTransactionsManager.php | 92 +++++++++ .../DatabaseTransactionsManagerTest.php | 174 ++++++++++++++++++ 3 files changed, 339 insertions(+) create mode 100755 src/Illuminate/Database/DatabaseTransactionRecord.php create mode 100755 src/Illuminate/Database/DatabaseTransactionsManager.php create mode 100755 tests/Database/DatabaseTransactionsManagerTest.php diff --git a/src/Illuminate/Database/DatabaseTransactionRecord.php b/src/Illuminate/Database/DatabaseTransactionRecord.php new file mode 100755 index 000000000000..b4556d8fc305 --- /dev/null +++ b/src/Illuminate/Database/DatabaseTransactionRecord.php @@ -0,0 +1,73 @@ +connection = $connection; + $this->level = $level; + } + + /** + * Register a callback to be executed after committing. + * + * @param callable $callback + * @return void + */ + public function addCallback($callback) + { + $this->callbacks[] = $callback; + } + + /** + * Execute all of the callbacks. + * + * @return void + */ + public function executeCallbacks() + { + foreach ($this->callbacks as $callback) { + call_user_func($callback); + } + } + + /** + * Get all of the callbacks. + * + * @return array + */ + public function getCallbacks() + { + return $this->callbacks; + } +} diff --git a/src/Illuminate/Database/DatabaseTransactionsManager.php b/src/Illuminate/Database/DatabaseTransactionsManager.php new file mode 100755 index 000000000000..e4f2f5fbb567 --- /dev/null +++ b/src/Illuminate/Database/DatabaseTransactionsManager.php @@ -0,0 +1,92 @@ +transactions = collect(); + } + + /** + * Start a new database transaction. + * + * @param string $connection + * @param int $level + * @return void + */ + public function begin($connection, $level) + { + $this->transactions->push( + new DatabaseTransactionRecord($connection, $level) + ); + } + + /** + * Rollback the active database transaction. + * + * @param string $connection + * @param int $level + * @return void + */ + public function rollback($connection, $level) + { + $this->transactions = $this->transactions->reject(function ($transaction) use ($connection, $level) { + return $transaction->connection == $connection && + $transaction->level >= $level; + })->values(); + } + + /** + * Commit the active database transaction. + * + * @param string $connection + * @return void + */ + public function commit($connection) + { + $this->transactions = $this->transactions->reject(function ($transaction) use ($connection) { + if ($transaction->connection == $connection) { + $transaction->executeCallbacks(); + + return true; + } + + return false; + })->values(); + } + + /** + * Register a transaction callback. + * + * @param callable $callback + * @return void. + */ + public function addCallback($callback) + { + $this->transactions->last()->addCallback($callback); + } + + /** + * Get all the transactions. + * + * @return \Illuminate\Support\Collection + */ + public function getTransactions() + { + return $this->transactions; + } +} diff --git a/tests/Database/DatabaseTransactionsManagerTest.php b/tests/Database/DatabaseTransactionsManagerTest.php new file mode 100755 index 000000000000..231a8ac9db55 --- /dev/null +++ b/tests/Database/DatabaseTransactionsManagerTest.php @@ -0,0 +1,174 @@ +begin('default', 1); + $manager->begin('default', 2); + $manager->begin('admin', 1); + + $this->assertCount(3, $manager->getTransactions()); + $this->assertEquals('default', $manager->getTransactions()[0]->connection); + $this->assertEquals(1, $manager->getTransactions()[0]->level); + $this->assertEquals('default', $manager->getTransactions()[1]->connection); + $this->assertEquals(2, $manager->getTransactions()[1]->level); + $this->assertEquals('admin', $manager->getTransactions()[2]->connection); + $this->assertEquals(1, $manager->getTransactions()[2]->level); + } + + public function testRollingBackTransactions() + { + $manager = (new DatabaseTransactionsManager()); + + $manager->begin('default', 1); + $manager->begin('default', 2); + $manager->begin('admin', 1); + + $manager->rollback('default', 2); + + $this->assertCount(2, $manager->getTransactions()); + + $this->assertEquals('default', $manager->getTransactions()[0]->connection); + $this->assertEquals(1, $manager->getTransactions()[0]->level); + + $this->assertEquals('admin', $manager->getTransactions()[1]->connection); + $this->assertEquals(1, $manager->getTransactions()[1]->level); + } + + public function testRollingBackTransactionsAllTheWay() + { + $manager = (new DatabaseTransactionsManager()); + + $manager->begin('default', 1); + $manager->begin('default', 2); + $manager->begin('admin', 1); + + $manager->rollback('default', 1); + + $this->assertCount(1, $manager->getTransactions()); + + $this->assertEquals('admin', $manager->getTransactions()[0]->connection); + $this->assertEquals(1, $manager->getTransactions()[0]->level); + } + + public function testCommittingTransactions() + { + $manager = (new DatabaseTransactionsManager()); + + $manager->begin('default', 1); + $manager->begin('default', 2); + $manager->begin('admin', 1); + + $manager->commit('default'); + + $this->assertCount(1, $manager->getTransactions()); + + $this->assertEquals('admin', $manager->getTransactions()[0]->connection); + $this->assertEquals(1, $manager->getTransactions()[0]->level); + } + + public function testCallbacksAreAddedToTheCurrentTransaction() + { + $callbacks = []; + + $manager = (new DatabaseTransactionsManager()); + + $manager->begin('default', 1); + + $manager->addCallback(function () use (&$callbacks) { + + }); + + $manager->begin('default', 2); + + $manager->begin('admin', 1); + + $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()); + } + + public function testCommittingTransactionsExecutesCallbacks() + { + $callbacks = []; + + $manager = (new DatabaseTransactionsManager()); + + $manager->begin('default', 1); + + $manager->addCallback(function () use (&$callbacks) { + $callbacks[] = ['default', 1]; + }); + + $manager->begin('default', 2); + + $manager->addCallback(function () use (&$callbacks) { + $callbacks[] = ['default', 2]; + }); + + $manager->begin('admin', 1); + + $manager->commit('default'); + + $this->assertCount(2, $callbacks); + $this->assertEquals(['default', 1], $callbacks[0]); + $this->assertEquals(['default', 2], $callbacks[1]); + } + + public function testCommittingExecutesOnlyCallbacksOfTheConnection() + { + $callbacks = []; + + $manager = (new DatabaseTransactionsManager()); + + $manager->begin('default', 1); + + $manager->addCallback(function () use (&$callbacks) { + $callbacks[] = ['default', 1]; + }); + + $manager->begin('default', 2); + $manager->begin('admin', 1); + + $manager->addCallback(function () use (&$callbacks) { + $callbacks[] = ['admin', 1]; + }); + + $manager->commit('default'); + + $this->assertCount(1, $callbacks); + $this->assertEquals(['default', 1], $callbacks[0]); + } +} From d09cd161f3789b125fe2de7df191eef5cb7dda0e Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Wed, 25 Nov 2020 18:26:55 +0200 Subject: [PATCH 2/7] register the transaction manager into the connection instance --- .../Database/Concerns/ManagesTransactions.php | 32 +++++++++++++++++++ src/Illuminate/Database/Connection.php | 30 +++++++++++++++++ src/Illuminate/Database/DatabaseManager.php | 4 +++ .../Database/DatabaseServiceProvider.php | 4 +++ .../Database/DatabaseTransactionsManager.php | 2 +- .../DatabaseTransactionsManagerTest.php | 4 +-- 6 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Database/Concerns/ManagesTransactions.php b/src/Illuminate/Database/Concerns/ManagesTransactions.php index 1dd4475290d6..7bf29ebef026 100644 --- a/src/Illuminate/Database/Concerns/ManagesTransactions.php +++ b/src/Illuminate/Database/Concerns/ManagesTransactions.php @@ -42,6 +42,10 @@ public function transaction(Closure $callback, $attempts = 1) try { if ($this->transactions == 1) { $this->getPdo()->commit(); + + if ($this->transactionsManager) { + $this->transactionsManager->commit($this->getName()); + } } $this->transactions = max(0, $this->transactions - 1); @@ -78,6 +82,12 @@ protected function handleTransactionException(Throwable $e, $currentAttempt, $ma $this->transactions > 1) { $this->transactions--; + if ($this->transactionsManager) { + $this->transactionsManager->rollback( + $this->getName(), $this->transactions + ); + } + throw $e; } @@ -107,6 +117,12 @@ public function beginTransaction() $this->transactions++; + if ($this->transactionsManager) { + $this->transactionsManager->begin( + $this->getName(), $this->transactions + ); + } + $this->fireConnectionEvent('beganTransaction'); } @@ -176,6 +192,10 @@ public function commit() { if ($this->transactions == 1) { $this->getPdo()->commit(); + + if ($this->transactionsManager) { + $this->transactionsManager->commit($this->getName()); + } } $this->transactions = max(0, $this->transactions - 1); @@ -241,6 +261,12 @@ public function rollBack($toLevel = null) $this->transactions = $toLevel; + if ($this->transactionsManager) { + $this->transactionsManager->rollback( + $this->getName(), $this->transactions + ); + } + $this->fireConnectionEvent('rollingBack'); } @@ -275,6 +301,12 @@ protected function handleRollBackException(Throwable $e) { if ($this->causedByLostConnection($e)) { $this->transactions = 0; + + if ($this->transactionsManager) { + $this->transactionsManager->rollback( + $this->getName(), $this->transactions + ); + } } throw $e; diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index 98f12639713e..ea8c41e908e8 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -112,6 +112,13 @@ class Connection implements ConnectionInterface */ protected $transactions = 0; + /** + * The transaction manager instance. + * + * @var \Illuminate\Database\DatabaseTransactionsManager + */ + protected $transactionsManager; + /** * Indicates if changes have been made to the database. * @@ -1151,6 +1158,29 @@ public function unsetEventDispatcher() $this->events = null; } + /** + * Set the transaction manager instance on the connection. + * + * @param \Illuminate\Database\DatabaseTransactionsManager $manager + * @return $this + */ + public function setTransactionManager($manager) + { + $this->transactionsManager = $manager; + + return $this; + } + + /** + * Unset the event transaction manager for this connection. + * + * @return void + */ + public function unsetTransactionManager() + { + $this->transactionsManager = null; + } + /** * Determine if the connection is in a "dry run". * diff --git a/src/Illuminate/Database/DatabaseManager.php b/src/Illuminate/Database/DatabaseManager.php index d558d1665fc8..7f8fdf921fb3 100755 --- a/src/Illuminate/Database/DatabaseManager.php +++ b/src/Illuminate/Database/DatabaseManager.php @@ -174,6 +174,10 @@ protected function configure(Connection $connection, $type) $connection->setEventDispatcher($this->app['events']); } + if ($this->app->bound('db.transactions')) { + $connection->setTransactionManager($this->app['db.transactions']); + } + // Here we'll set a reconnector callback. This reconnector can be any callable // so we will set a Closure to reconnect from this manager with the name of // the connection, which will allow us to reconnect from the connections. diff --git a/src/Illuminate/Database/DatabaseServiceProvider.php b/src/Illuminate/Database/DatabaseServiceProvider.php index f64f8f2683d5..d8f87227ae07 100755 --- a/src/Illuminate/Database/DatabaseServiceProvider.php +++ b/src/Illuminate/Database/DatabaseServiceProvider.php @@ -71,6 +71,10 @@ protected function registerConnectionServices() $this->app->bind('db.connection', function ($app) { return $app['db']->connection(); }); + + $this->app->singleton('db.transactions', function ($app) { + return new DatabaseTransactionsManager(); + }); } /** diff --git a/src/Illuminate/Database/DatabaseTransactionsManager.php b/src/Illuminate/Database/DatabaseTransactionsManager.php index e4f2f5fbb567..37be16448bea 100755 --- a/src/Illuminate/Database/DatabaseTransactionsManager.php +++ b/src/Illuminate/Database/DatabaseTransactionsManager.php @@ -46,7 +46,7 @@ public function rollback($connection, $level) { $this->transactions = $this->transactions->reject(function ($transaction) use ($connection, $level) { return $transaction->connection == $connection && - $transaction->level >= $level; + $transaction->level > $level; })->values(); } diff --git a/tests/Database/DatabaseTransactionsManagerTest.php b/tests/Database/DatabaseTransactionsManagerTest.php index 231a8ac9db55..4d92819e3996 100755 --- a/tests/Database/DatabaseTransactionsManagerTest.php +++ b/tests/Database/DatabaseTransactionsManagerTest.php @@ -52,7 +52,7 @@ public function testRollingBackTransactions() $manager->begin('default', 2); $manager->begin('admin', 1); - $manager->rollback('default', 2); + $manager->rollback('default', 1); $this->assertCount(2, $manager->getTransactions()); @@ -71,7 +71,7 @@ public function testRollingBackTransactionsAllTheWay() $manager->begin('default', 2); $manager->begin('admin', 1); - $manager->rollback('default', 1); + $manager->rollback('default', 0); $this->assertCount(1, $manager->getTransactions()); From fc1f3e3fa117f82bc5669c6cc23f8db87651d1c4 Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Thu, 26 Nov 2020 14:47:02 +0200 Subject: [PATCH 3/7] add tests --- tests/Database/DatabaseTransactionsTest.php | 257 ++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 tests/Database/DatabaseTransactionsTest.php diff --git a/tests/Database/DatabaseTransactionsTest.php b/tests/Database/DatabaseTransactionsTest.php new file mode 100644 index 000000000000..0432d750656f --- /dev/null +++ b/tests/Database/DatabaseTransactionsTest.php @@ -0,0 +1,257 @@ +addConnection([ + 'driver' => 'sqlite', + 'database' => ':memory:', + ]); + + $db->addConnection([ + 'driver' => 'sqlite', + 'database' => ':memory:', + ], 'second_connection'); + + $db->setAsGlobal(); + + $this->createSchema(); + } + + protected function createSchema() + { + foreach (['default', 'second_connection'] as $connection) { + $this->schema($connection)->create('users', function ($table) { + $table->increments('id'); + $table->string('name')->nullable(); + $table->string('value')->nullable(); + }); + } + } + + /** + * Tear down the database schema. + * + * @return void + */ + protected function tearDown(): void + { + foreach (['default', 'second_connection'] as $connection) { + $this->schema($connection)->drop('users'); + } + + m::close(); + } + + public function testTransactionIsRecordedAndCommitted() + { + $transactionManager = m::mock(new DatabaseTransactionsManager()); + $transactionManager->shouldReceive('begin')->once()->with('default', 1); + $transactionManager->shouldReceive('commit')->once()->with('default'); + + $this->connection()->setTransactionManager($transactionManager); + + $this->connection()->table('users')->insert([ + 'name' => 'zain', 'value' => 1 + ]); + + $this->connection()->transaction(function() use ($transactionManager){ + $this->connection()->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + }); + } + + public function testTransactionIsRecordedAndCommittedUsingTheSeparateMethods() + { + $transactionManager = m::mock(new DatabaseTransactionsManager()); + $transactionManager->shouldReceive('begin')->once()->with('default', 1); + $transactionManager->shouldReceive('commit')->once()->with('default'); + + $this->connection()->setTransactionManager($transactionManager); + + $this->connection()->table('users')->insert([ + 'name' => 'zain', 'value' => 1 + ]); + + $this->connection()->beginTransaction(); + $this->connection()->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + $this->connection()->commit(); + } + + public function testNestedTransactionIsRecordedAndCommitted() + { + $transactionManager = m::mock(new DatabaseTransactionsManager()); + $transactionManager->shouldReceive('begin')->once()->with('default', 1); + $transactionManager->shouldReceive('begin')->once()->with('default', 2); + $transactionManager->shouldReceive('commit')->once()->with('default'); + + $this->connection()->setTransactionManager($transactionManager); + + $this->connection()->table('users')->insert([ + 'name' => 'zain', 'value' => 1 + ]); + + $this->connection()->transaction(function() use ($transactionManager){ + $this->connection()->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + + $this->connection()->transaction(function() use ($transactionManager){ + $this->connection()->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + }); + }); + } + + public function testNestedTransactionIsRecordeForDifferentConnectionsdAndCommitted() + { + $transactionManager = m::mock(new DatabaseTransactionsManager()); + $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('commit')->once()->with('default'); + $transactionManager->shouldReceive('commit')->once()->with('second_connection'); + + $this->connection()->setTransactionManager($transactionManager); + $this->connection('second_connection')->setTransactionManager($transactionManager); + + $this->connection()->table('users')->insert([ + 'name' => 'zain', 'value' => 1 + ]); + + $this->connection()->transaction(function() use ($transactionManager){ + $this->connection()->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + + $this->connection('second_connection')->transaction(function() use ($transactionManager){ + $this->connection('second_connection')->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + + $this->connection('second_connection')->transaction(function() use ($transactionManager){ + $this->connection('second_connection')->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + }); + }); + }); + } + + public function testTransactionIsRolledBack() + { + $transactionManager = m::mock(new DatabaseTransactionsManager()); + $transactionManager->shouldReceive('begin')->once()->with('default', 1); + $transactionManager->shouldReceive('rollback')->once()->with('default', 0); + $transactionManager->shouldNotReceive('commit'); + + $this->connection()->setTransactionManager($transactionManager); + + $this->connection()->table('users')->insert([ + 'name' => 'zain', 'value' => 1 + ]); + + try { + $this->connection()->transaction(function () use ($transactionManager) { + $this->connection()->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + + throw new \Exception; + }); + } catch (\Throwable $e) { + + } + } + + public function testTransactionIsRolledBackUsingSeparateMethods() + { + $transactionManager = m::mock(new DatabaseTransactionsManager()); + $transactionManager->shouldReceive('begin')->once()->with('default', 1); + $transactionManager->shouldReceive('rollback')->once()->with('default', 0); + $transactionManager->shouldNotReceive('commit'); + + $this->connection()->setTransactionManager($transactionManager); + + $this->connection()->table('users')->insert([ + 'name' => 'zain', 'value' => 1 + ]); + + $this->connection()->beginTransaction(); + + $this->connection()->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + + $this->connection()->rollBack(); + } + + public function testNestedTransactionsAreRolledBack() + { + $transactionManager = m::mock(new DatabaseTransactionsManager()); + $transactionManager->shouldReceive('begin')->once()->with('default', 1); + $transactionManager->shouldReceive('begin')->once()->with('default', 2); + $transactionManager->shouldReceive('rollback')->once()->with('default', 1); + $transactionManager->shouldReceive('rollback')->once()->with('default', 0); + $transactionManager->shouldNotReceive('commit'); + + $this->connection()->setTransactionManager($transactionManager); + + $this->connection()->table('users')->insert([ + 'name' => 'zain', 'value' => 1 + ]); + + try { + $this->connection()->transaction(function () use ($transactionManager) { + $this->connection()->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + + $this->connection()->transaction(function () use ($transactionManager) { + $this->connection()->table('users')->where(['name' => 'zain'])->update([ + 'value' => 2 + ]); + + throw new \Exception; + }); + }); + } catch (\Throwable $e) { + + } + } + + + /** + * Get a schema builder instance. + * + * @return \Illuminate\Database\Schema\Builder + */ + protected function schema($connection = 'default') + { + return $this->connection($connection)->getSchemaBuilder(); + } + + public function connection($name = 'default') + { + return DB::connection($name); + } +} From 923e277ad2e68cac3c1e2b1d4d259e480536026c Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Thu, 26 Nov 2020 15:11:40 +0200 Subject: [PATCH 4/7] add withinTransaction --- .../Database/Concerns/ManagesTransactions.php | 15 +++++++++++++++ .../Database/DatabaseTransactionsManager.php | 6 +++++- .../Database/DatabaseTransactionsManagerTest.php | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Concerns/ManagesTransactions.php b/src/Illuminate/Database/Concerns/ManagesTransactions.php index 7bf29ebef026..68eb2fefe7a8 100644 --- a/src/Illuminate/Database/Concerns/ManagesTransactions.php +++ b/src/Illuminate/Database/Concerns/ManagesTransactions.php @@ -3,6 +3,7 @@ namespace Illuminate\Database\Concerns; use Closure; +use RuntimeException; use Throwable; trait ManagesTransactions @@ -321,4 +322,18 @@ public function transactionLevel() { return $this->transactions; } + + /** + * Execute the callback within a transaction context. + * + * @return void + */ + public function withinTransaction($callback) + { + if ($this->transactionsManager) { + return $this->transactionsManager->addCallback($callback); + } + + throw new RuntimeException('Transactions Manager has not been set.'); + } } diff --git a/src/Illuminate/Database/DatabaseTransactionsManager.php b/src/Illuminate/Database/DatabaseTransactionsManager.php index 37be16448bea..95462a331c8f 100755 --- a/src/Illuminate/Database/DatabaseTransactionsManager.php +++ b/src/Illuminate/Database/DatabaseTransactionsManager.php @@ -77,7 +77,11 @@ public function commit($connection) */ public function addCallback($callback) { - $this->transactions->last()->addCallback($callback); + if ($current = $this->transactions->last()) { + return $current->addCallback($callback); + } + + call_user_func($callback); } /** diff --git a/tests/Database/DatabaseTransactionsManagerTest.php b/tests/Database/DatabaseTransactionsManagerTest.php index 4d92819e3996..b065c24f6e21 100755 --- a/tests/Database/DatabaseTransactionsManagerTest.php +++ b/tests/Database/DatabaseTransactionsManagerTest.php @@ -171,4 +171,18 @@ public function testCommittingExecutesOnlyCallbacksOfTheConnection() $this->assertCount(1, $callbacks); $this->assertEquals(['default', 1], $callbacks[0]); } + + public function testCallbackIsExecutedIfNoTransactions() + { + $callbacks = []; + + $manager = (new DatabaseTransactionsManager()); + + $manager->addCallback(function () use (&$callbacks) { + $callbacks[] = ['default', 1]; + }); + + $this->assertCount(1, $callbacks); + $this->assertEquals(['default', 1], $callbacks[0]); + } } From 127bbe7271099dd324988603c913151d0de6f16c Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Thu, 26 Nov 2020 15:24:00 +0200 Subject: [PATCH 5/7] fix style --- .../DatabaseTransactionsManagerTest.php | 22 ----------- tests/Database/DatabaseTransactionsTest.php | 39 +++++++++---------- 2 files changed, 18 insertions(+), 43 deletions(-) diff --git a/tests/Database/DatabaseTransactionsManagerTest.php b/tests/Database/DatabaseTransactionsManagerTest.php index b065c24f6e21..172a48e5a4a1 100755 --- a/tests/Database/DatabaseTransactionsManagerTest.php +++ b/tests/Database/DatabaseTransactionsManagerTest.php @@ -2,28 +2,8 @@ namespace Illuminate\Tests\Database; -use DateTime; -use ErrorException; -use Exception; -use Illuminate\Contracts\Events\Dispatcher; -use Illuminate\Database\Connection; use Illuminate\Database\DatabaseTransactionsManager; -use Illuminate\Database\Events\QueryExecuted; -use Illuminate\Database\Events\TransactionBeginning; -use Illuminate\Database\Events\TransactionCommitted; -use Illuminate\Database\Events\TransactionRolledBack; -use Illuminate\Database\Query\Builder as BaseBuilder; -use Illuminate\Database\Query\Grammars\Grammar; -use Illuminate\Database\Query\Processors\Processor; -use Illuminate\Database\QueryException; -use Illuminate\Database\Schema\Builder; -use Mockery as m; -use PDO; -use PDOException; -use PDOStatement; use PHPUnit\Framework\TestCase; -use ReflectionClass; -use stdClass; class DatabaseTransactionsManagerTest extends TestCase { @@ -104,7 +84,6 @@ public function testCallbacksAreAddedToTheCurrentTransaction() $manager->begin('default', 1); $manager->addCallback(function () use (&$callbacks) { - }); $manager->begin('default', 2); @@ -112,7 +91,6 @@ public function testCallbacksAreAddedToTheCurrentTransaction() $manager->begin('admin', 1); $manager->addCallback(function () use (&$callbacks) { - }); $this->assertCount(1, $manager->getTransactions()[0]->getCallbacks()); diff --git a/tests/Database/DatabaseTransactionsTest.php b/tests/Database/DatabaseTransactionsTest.php index 0432d750656f..a2bd36114b9c 100644 --- a/tests/Database/DatabaseTransactionsTest.php +++ b/tests/Database/DatabaseTransactionsTest.php @@ -67,12 +67,12 @@ public function testTransactionIsRecordedAndCommitted() $this->connection()->setTransactionManager($transactionManager); $this->connection()->table('users')->insert([ - 'name' => 'zain', 'value' => 1 + 'name' => 'zain', 'value' => 1, ]); $this->connection()->transaction(function() use ($transactionManager){ $this->connection()->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); }); } @@ -86,12 +86,12 @@ public function testTransactionIsRecordedAndCommittedUsingTheSeparateMethods() $this->connection()->setTransactionManager($transactionManager); $this->connection()->table('users')->insert([ - 'name' => 'zain', 'value' => 1 + 'name' => 'zain', 'value' => 1, ]); $this->connection()->beginTransaction(); $this->connection()->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); $this->connection()->commit(); } @@ -106,17 +106,17 @@ public function testNestedTransactionIsRecordedAndCommitted() $this->connection()->setTransactionManager($transactionManager); $this->connection()->table('users')->insert([ - 'name' => 'zain', 'value' => 1 + 'name' => 'zain', 'value' => 1, ]); $this->connection()->transaction(function() use ($transactionManager){ $this->connection()->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); $this->connection()->transaction(function() use ($transactionManager){ $this->connection()->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); }); }); @@ -135,22 +135,22 @@ public function testNestedTransactionIsRecordeForDifferentConnectionsdAndCommitt $this->connection('second_connection')->setTransactionManager($transactionManager); $this->connection()->table('users')->insert([ - 'name' => 'zain', 'value' => 1 + 'name' => 'zain', 'value' => 1, ]); $this->connection()->transaction(function() use ($transactionManager){ $this->connection()->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); $this->connection('second_connection')->transaction(function() use ($transactionManager){ $this->connection('second_connection')->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); $this->connection('second_connection')->transaction(function() use ($transactionManager){ $this->connection('second_connection')->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); }); }); @@ -167,19 +167,18 @@ public function testTransactionIsRolledBack() $this->connection()->setTransactionManager($transactionManager); $this->connection()->table('users')->insert([ - 'name' => 'zain', 'value' => 1 + 'name' => 'zain', 'value' => 1, ]); try { $this->connection()->transaction(function () use ($transactionManager) { $this->connection()->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); throw new \Exception; }); } catch (\Throwable $e) { - } } @@ -193,13 +192,13 @@ public function testTransactionIsRolledBackUsingSeparateMethods() $this->connection()->setTransactionManager($transactionManager); $this->connection()->table('users')->insert([ - 'name' => 'zain', 'value' => 1 + 'name' => 'zain', 'value' => 1, ]); $this->connection()->beginTransaction(); $this->connection()->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); $this->connection()->rollBack(); @@ -217,29 +216,27 @@ public function testNestedTransactionsAreRolledBack() $this->connection()->setTransactionManager($transactionManager); $this->connection()->table('users')->insert([ - 'name' => 'zain', 'value' => 1 + 'name' => 'zain', 'value' => 1, ]); try { $this->connection()->transaction(function () use ($transactionManager) { $this->connection()->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); $this->connection()->transaction(function () use ($transactionManager) { $this->connection()->table('users')->where(['name' => 'zain'])->update([ - 'value' => 2 + 'value' => 2, ]); throw new \Exception; }); }); } catch (\Throwable $e) { - } } - /** * Get a schema builder instance. * From c4fe69ec8318bfb8ab847e962ad6b8c1353cbc20 Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Thu, 26 Nov 2020 15:27:01 +0200 Subject: [PATCH 6/7] fix style --- tests/Database/DatabaseTransactionsTest.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/Database/DatabaseTransactionsTest.php b/tests/Database/DatabaseTransactionsTest.php index a2bd36114b9c..2385d6d26313 100644 --- a/tests/Database/DatabaseTransactionsTest.php +++ b/tests/Database/DatabaseTransactionsTest.php @@ -70,7 +70,7 @@ public function testTransactionIsRecordedAndCommitted() 'name' => 'zain', 'value' => 1, ]); - $this->connection()->transaction(function() use ($transactionManager){ + $this->connection()->transaction(function () { $this->connection()->table('users')->where(['name' => 'zain'])->update([ 'value' => 2, ]); @@ -109,12 +109,12 @@ public function testNestedTransactionIsRecordedAndCommitted() 'name' => 'zain', 'value' => 1, ]); - $this->connection()->transaction(function() use ($transactionManager){ + $this->connection()->transaction(function () { $this->connection()->table('users')->where(['name' => 'zain'])->update([ 'value' => 2, ]); - $this->connection()->transaction(function() use ($transactionManager){ + $this->connection()->transaction(function () { $this->connection()->table('users')->where(['name' => 'zain'])->update([ 'value' => 2, ]); @@ -138,17 +138,17 @@ public function testNestedTransactionIsRecordeForDifferentConnectionsdAndCommitt 'name' => 'zain', 'value' => 1, ]); - $this->connection()->transaction(function() use ($transactionManager){ + $this->connection()->transaction(function () { $this->connection()->table('users')->where(['name' => 'zain'])->update([ 'value' => 2, ]); - $this->connection('second_connection')->transaction(function() use ($transactionManager){ + $this->connection('second_connection')->transaction(function () { $this->connection('second_connection')->table('users')->where(['name' => 'zain'])->update([ 'value' => 2, ]); - $this->connection('second_connection')->transaction(function() use ($transactionManager){ + $this->connection('second_connection')->transaction(function () { $this->connection('second_connection')->table('users')->where(['name' => 'zain'])->update([ 'value' => 2, ]); @@ -171,7 +171,7 @@ public function testTransactionIsRolledBack() ]); try { - $this->connection()->transaction(function () use ($transactionManager) { + $this->connection()->transaction(function () { $this->connection()->table('users')->where(['name' => 'zain'])->update([ 'value' => 2, ]); @@ -220,12 +220,12 @@ public function testNestedTransactionsAreRolledBack() ]); try { - $this->connection()->transaction(function () use ($transactionManager) { + $this->connection()->transaction(function () { $this->connection()->table('users')->where(['name' => 'zain'])->update([ 'value' => 2, ]); - $this->connection()->transaction(function () use ($transactionManager) { + $this->connection()->transaction(function () { $this->connection()->table('users')->where(['name' => 'zain'])->update([ 'value' => 2, ]); From 04df2e1dddd287a6f560464e0739e49628553d30 Mon Sep 17 00:00:00 2001 From: Mohamed Said Date: Thu, 26 Nov 2020 18:38:59 +0200 Subject: [PATCH 7/7] rename to afterCommit --- src/Illuminate/Database/Concerns/ManagesTransactions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Database/Concerns/ManagesTransactions.php b/src/Illuminate/Database/Concerns/ManagesTransactions.php index 68eb2fefe7a8..0d7b9a2e944d 100644 --- a/src/Illuminate/Database/Concerns/ManagesTransactions.php +++ b/src/Illuminate/Database/Concerns/ManagesTransactions.php @@ -324,11 +324,11 @@ public function transactionLevel() } /** - * Execute the callback within a transaction context. + * Execute the callback after a transaction commits. * * @return void */ - public function withinTransaction($callback) + public function afterCommit($callback) { if ($this->transactionsManager) { return $this->transactionsManager->addCallback($callback);