From 44dd3cfa67f7b8f64482467c7bad01afb42e2b32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Wed, 29 Nov 2023 09:17:26 +0100 Subject: [PATCH] fix: Add reconnect check in case of timeouts on the db side MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/private/DB/Connection.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php index e3fda3e464fdb..ca7e9eeae2a75 100644 --- a/lib/private/DB/Connection.php +++ b/lib/private/DB/Connection.php @@ -41,6 +41,7 @@ use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection; use Doctrine\DBAL\Driver; use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Exception\ConnectionLost; use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\DBAL\Platforms\OraclePlatform; use Doctrine\DBAL\Platforms\SqlitePlatform; @@ -78,6 +79,7 @@ class Connection extends PrimaryReadReplicaConnection { /** @var DbDataCollector|null */ protected $dbDataCollector = null; + private int $lastConnectionCheck = 0; /** * Initializes a new instance of the Connection class. @@ -123,10 +125,13 @@ public function __construct( public function connect($connectionName = null) { try { if ($this->_conn) { + $this->reconnectIfNeeded(); /** @psalm-suppress InternalMethod */ return parent::connect(); } + $this->lastConnectionCheck = time(); + // Only trigger the event logger for the initial connect call $eventLogger = \OC::$server->get(IEventLogger::class); $eventLogger->start('connect:db', 'db connection opened'); @@ -618,4 +623,18 @@ protected function performConnect(?string $connectionName = null): bool { } return $result; } + + private function reconnectIfNeeded(): void { + if ($this->lastConnectionCheck + 30 >= time() || $this->isTransactionActive()) { + return; + } + + try { + $this->_conn->query($this->getDriver()->getDatabasePlatform()->getDummySelectSQL()); + $this->lastConnectionCheck = time(); + } catch (ConnectionLost|\Exception $e) { + $this->logger->warning('Exception during connectivity check, closing and reconnecting', ['exception' => $e]); + $this->close(); + } + } }