diff options
author | Julius Härtl <jus@bitgrid.net> | 2023-11-29 09:17:26 +0100 |
---|---|---|
committer | Julius Härtl <jus@bitgrid.net> | 2024-01-12 14:38:01 +0100 |
commit | 296096e06996aee1a06d901b99adde5f04688f58 (patch) | |
tree | 0f929bee7bf7f4e4d729ae5b7d79f8e4006ee8fc /lib | |
parent | 48628b90690d8204e7875d561b8115c526cc9176 (diff) | |
download | nextcloud-server-296096e06996aee1a06d901b99adde5f04688f58.tar.gz nextcloud-server-296096e06996aee1a06d901b99adde5f04688f58.zip |
fix: Add reconnect check in case of timeouts on the db side
Signed-off-by: Julius Härtl <jus@bitgrid.net>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/DB/Connection.php | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/lib/private/DB/Connection.php b/lib/private/DB/Connection.php index a5f41cc66c9..b65f4520290 100644 --- a/lib/private/DB/Connection.php +++ b/lib/private/DB/Connection.php @@ -41,6 +41,7 @@ use Doctrine\DBAL\Configuration; 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 array $lastConnectionCheck = []; protected ?float $transactionActiveSince = null; @@ -127,10 +129,13 @@ class Connection extends PrimaryReadReplicaConnection { public function connect($connectionName = null) { try { if ($this->_conn) { + $this->reconnectIfNeeded(); /** @psalm-suppress InternalMethod */ return parent::connect(); } + $this->lastConnectionCheck[$this->getConnectionName()] = time(); + // Only trigger the event logger for the initial connect call $eventLogger = \OC::$server->get(IEventLogger::class); $eventLogger->start('connect:db', 'db connection opened'); @@ -679,4 +684,26 @@ class Connection extends PrimaryReadReplicaConnection { } return $result; } + + private function reconnectIfNeeded(): void { + if ( + !isset($this->lastConnectionCheck[$this->getConnectionName()]) || + $this->lastConnectionCheck[$this->getConnectionName()] + 30 >= time() || + $this->isTransactionActive() + ) { + return; + } + + try { + $this->_conn->query($this->getDriver()->getDatabasePlatform()->getDummySelectSQL()); + $this->lastConnectionCheck[$this->getConnectionName()] = time(); + } catch (ConnectionLost|\Exception $e) { + $this->logger->warning('Exception during connectivity check, closing and reconnecting', ['exception' => $e]); + $this->close(); + } + } + + private function getConnectionName(): string { + return $this->isConnectedToPrimary() ? 'primary' : 'replica'; + } } |