framework icon indicating copy to clipboard operation
framework copied to clipboard

[10.x] After commit callback throwing an exception causes transaction level to be incorrect

Open oprypkhantc opened this issue 1 year ago • 0 comments

Hey.

Whenever an afterCommit callback throws an exception inside of a DB::transaction() closure, it's caught by the ManagesTransactions trait and internal ->transactions transaction level is decremented. In tests that use DatabaseTransactions trait this makes DB::transactionLevel() return 0, although the real transaction level (on the database side) is still 1.

class SomeTest extends TestCase 
{
    use DatabaseTransactions;

    public function testSomething()
    {
        $this->assertSame(1, DB::transactionLevel());
    
        try {
            DB::transaction(function () {
                $this->assertSame(2, DB::transactionLevel());
            
                DB::afterCommit(fn () => throw new \RuntimeException());
            });
        } catch (\RuntimeException) {}
        
        // Currently fails
        $this->assertSame(1, DB::transactionLevel());
    }
}

This PR fixes this by running after commit callbacks outside of the try-catch, next to the "committing" event.

oprypkhantc avatar Feb 14 '24 14:02 oprypkhantc