Skip to content

Commit

Permalink
naive solution
Browse files Browse the repository at this point in the history
  • Loading branch information
mateusjatenee committed Oct 30, 2023
1 parent 8052b38 commit ef46049
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 7 deletions.
5 changes: 3 additions & 2 deletions src/Illuminate/Database/Concerns/ManagesTransactions.php
Expand Up @@ -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');
Expand Down Expand Up @@ -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');
Expand Down
7 changes: 7 additions & 0 deletions src/Illuminate/Database/Connection.php
Expand Up @@ -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.
*
Expand Down
11 changes: 10 additions & 1 deletion src/Illuminate/Database/DatabaseTransactionRecord.php
Expand Up @@ -18,6 +18,13 @@ class DatabaseTransactionRecord
*/
public $level;

/**
* The transaction counter.
*
* @var int
*/
public $counter;

/**
* The callbacks that should be executed after committing.
*
Expand All @@ -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;
}

/**
Expand Down
10 changes: 6 additions & 4 deletions src/Illuminate/Database/DatabaseTransactionsManager.php
Expand Up @@ -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)
);
}

Expand All @@ -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();
}

Expand Down
3 changes: 3 additions & 0 deletions tests/Integration/Database/DatabaseTransactionsTest.php
Expand Up @@ -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
Expand Down

0 comments on commit ef46049

Please sign in to comment.