From cacec40ffbef700f683c03f62f2d888dc31c2a13 Mon Sep 17 00:00:00 2001 From: Allison Guilhem Date: Thu, 4 Apr 2024 23:45:51 +1100 Subject: [PATCH] In long-running processes, allows checking the database connection by pinging it, thus avoiding exceptions. Additionally, it provides the flexibility to configure the frequency of the check to be performed in the case of long-running processes. --- src/Connection.php | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/Connection.php b/src/Connection.php index 76b427b5b38..6d2cda176fb 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -17,6 +17,7 @@ use Doctrine\DBAL\Exception\ConnectionLost; use Doctrine\DBAL\Exception\DriverException; use Doctrine\DBAL\Exception\InvalidArgumentException; +use Doctrine\DBAL\Exception as DBALException; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Query\Expression\ExpressionBuilder; use Doctrine\DBAL\Query\QueryBuilder; @@ -166,6 +167,12 @@ class Connection private SchemaManagerFactory $schemaManagerFactory; + private static bool $isChecking = false; + + private static ?int $lastCheckedAt = null; + + private ?int $checkFrequency; + /** * Initializes a new instance of the Connection class. * @@ -186,6 +193,7 @@ public function __construct( ?Configuration $config = null, ?EventManager $eventManager = null ) { + $this->checkFrequency = $params['check_connection_frequency'] ?? null; $this->_driver = $driver; $this->params = $params; @@ -371,6 +379,21 @@ public function connect() ); if ($this->_conn !== null) { + if (null === $this->checkFrequency) { + return false; + } + + if (! self::$isChecking) { + if (null === self::$lastCheckedAt || time() - self::$lastCheckedAt >= $this->checkFrequency) { + self::$isChecking = true; + + $this->reconnectOnFailure(); + + self::$lastCheckedAt = time(); + self::$isChecking = false; + } + } + return false; } @@ -2002,4 +2025,15 @@ public function exec(string $sql): int return $this->executeStatement($sql); } + + private function reconnectOnFailure() + { + try { + $this->executeQuery($this->getDatabasePlatform($this)->getDummySelectSQL()); + } catch (DBALException) { + $this->close(); + // Attempt to reestablish the lazy connection by sending another query. + $this->executeQuery($this->getDatabasePlatform($this)->getDummySelectSQL()); + } + } }