fix: Add reconnect check in case of timeouts on the db side

Signed-off-by: Julius Härtl <jus@bitgrid.net>
pull/41819/head
Julius Härtl 2023-11-29 09:17:26 +07:00
parent 48628b9069
commit 296096e069
No known key found for this signature in database
GPG Key ID: 4C614C6ED2CDE6DF
1 changed files with 27 additions and 0 deletions

@ -41,6 +41,7 @@ use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection; use Doctrine\DBAL\Connections\PrimaryReadReplicaConnection;
use Doctrine\DBAL\Driver; use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Exception; use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Exception\ConnectionLost;
use Doctrine\DBAL\Platforms\MySQLPlatform; use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform; use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Platforms\SqlitePlatform;
@ -78,6 +79,7 @@ class Connection extends PrimaryReadReplicaConnection {
/** @var DbDataCollector|null */ /** @var DbDataCollector|null */
protected $dbDataCollector = null; protected $dbDataCollector = null;
private array $lastConnectionCheck = [];
protected ?float $transactionActiveSince = null; protected ?float $transactionActiveSince = null;
@ -127,10 +129,13 @@ class Connection extends PrimaryReadReplicaConnection {
public function connect($connectionName = null) { public function connect($connectionName = null) {
try { try {
if ($this->_conn) { if ($this->_conn) {
$this->reconnectIfNeeded();
/** @psalm-suppress InternalMethod */ /** @psalm-suppress InternalMethod */
return parent::connect(); return parent::connect();
} }
$this->lastConnectionCheck[$this->getConnectionName()] = time();
// Only trigger the event logger for the initial connect call // Only trigger the event logger for the initial connect call
$eventLogger = \OC::$server->get(IEventLogger::class); $eventLogger = \OC::$server->get(IEventLogger::class);
$eventLogger->start('connect:db', 'db connection opened'); $eventLogger->start('connect:db', 'db connection opened');
@ -679,4 +684,26 @@ class Connection extends PrimaryReadReplicaConnection {
} }
return $result; 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';
}
} }