Skip to content

Commit 1b76fa2

Browse files
committed
fix(database): harden worker transaction cleanup
- Catch rollback callback exceptions during worker cleanup - Log cleanup callback failures as critical - Add regression coverage for worker-mode rollback cleanup Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
1 parent eaebe19 commit 1b76fa2

2 files changed

Lines changed: 24 additions & 1 deletion

File tree

system/Database/Config.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use CodeIgniter\Config\BaseConfig;
1717
use CodeIgniter\Exceptions\InvalidArgumentException;
1818
use Config\Database as DbConfig;
19+
use Throwable;
1920

2021
/**
2122
* @see \CodeIgniter\Database\ConfigTest
@@ -184,7 +185,12 @@ public static function cleanupForWorkerMode(): void
184185
log_message('error', "Uncommitted transaction detected in database group '{$group}'. Transactions must be completed before request ends.");
185186

186187
while ($connection->transDepth > 0) {
187-
$connection->transRollback();
188+
try {
189+
$connection->transRollback();
190+
} catch (Throwable $e) {
191+
log_message('critical', $e->getMessage());
192+
break;
193+
}
188194
}
189195
}
190196

tests/system/Database/Live/WorkerModeTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use CodeIgniter\Test\CIUnitTestCase;
1919
use CodeIgniter\Test\DatabaseTestTrait;
2020
use PHPUnit\Framework\Attributes\Group;
21+
use RuntimeException;
2122

2223
/**
2324
* @internal
@@ -48,6 +49,22 @@ public function testCleanupForWorkerMode(): void
4849
$this->assertNotFalse($this->getPrivateProperty($conn, 'connID'));
4950
}
5051

52+
public function testCleanupForWorkerModeLogsRollbackCallbackException(): void
53+
{
54+
$conn = Config::connect();
55+
$this->assertInstanceOf(BaseConnection::class, $conn);
56+
57+
$conn->transStart();
58+
$conn->afterRollback(static function (): void {
59+
throw new RuntimeException('Rollback callback failed.');
60+
});
61+
62+
Config::cleanupForWorkerMode();
63+
64+
$this->assertSame(0, $conn->transDepth);
65+
$this->assertLogged('critical', 'Rollback callback failed.');
66+
}
67+
5168
public function testReconnectForWorkerMode(): void
5269
{
5370
$conn = Config::connect();

0 commit comments

Comments
 (0)