Skip to content

Commit

Permalink
Handle lost connection during commit
Browse files Browse the repository at this point in the history
  • Loading branch information
morozov committed Jul 16, 2021
1 parent d845b3d commit 07136aa
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,8 @@ public function commit(): void

try {
$connection->commit();
} catch (Driver\Exception $e) {
throw $this->convertException($e);
} finally {
$logger->stopQuery();
}
Expand Down Expand Up @@ -1298,6 +1300,8 @@ public function rollBack(): void

try {
$connection->rollBack();
} catch (Driver\Exception $e) {
throw $this->convertException($e);
} finally {
$this->isRollbackOnly = false;
$logger->stopQuery();
Expand Down
12 changes: 10 additions & 2 deletions src/Driver/PDO/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,20 @@ public function beginTransaction(): void

public function commit(): void
{
$this->connection->commit();
try {
$this->connection->commit();
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}

public function rollBack(): void
{
$this->connection->rollBack();
try {
$this->connection->rollBack();
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}

public function getWrappedConnection(): PDO
Expand Down
64 changes: 64 additions & 0 deletions tests/Functional/TransactionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Tests\Functional;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\PDO;
use Doctrine\DBAL\Exception\ConnectionLost;
use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Tests\FunctionalTestCase;

use function sleep;

use const E_ALL;
use const E_WARNING;
use const PHP_VERSION_ID;

class TransactionTest extends FunctionalTestCase
{
protected function setUp(): void
{
parent::setUp();

if ($this->connection->getDatabasePlatform() instanceof MySQLPlatform) {
return;
}

self::markTestSkipped('Restricted to MySQL.');
}

public function testCommitFailure(): void
{
$this->expectConnectionLoss(static function (Connection $connection): void {
$connection->commit();
});
}

public function testRollbackFailure(): void
{
$this->expectConnectionLoss(static function (Connection $connection): void {
$connection->rollBack();
});
}

private function expectConnectionLoss(callable $scenario): void
{
if (PHP_VERSION_ID < 70413 && $this->connection->getDriver() instanceof PDO\MySQL\Driver) {
self::markTestSkipped('See https://bugs.php.net/bug.php?id=66528.');
}

$this->connection->executeStatement('SET SESSION wait_timeout=1');
$this->connection->beginTransaction();

// during the sleep MySQL will close the connection
sleep(2);

// prevent the PHPUnit error handler from handling the "MySQL server has gone away" warning
$this->iniSet('error_reporting', (string) (E_ALL & ~E_WARNING));

$this->expectException(ConnectionLost::class);
$scenario($this->connection);
}
}

0 comments on commit 07136aa

Please sign in to comment.