This commit is contained in:
Enoch
2024-08-09 22:16:39 +08:00
commit d78b38e80f
3984 changed files with 416946 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 4.2.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Database\Retry;
use Cake\Core\Retry\RetryStrategyInterface;
use Exception;
use PDOException;
/**
* Implements retry strategy based on db error codes and wait interval.
*
* @internal
*/
class ErrorCodeWaitStrategy implements RetryStrategyInterface
{
/**
* @var array<int>
*/
protected $errorCodes;
/**
* @var int
*/
protected $retryInterval;
/**
* @param array<int> $errorCodes DB-specific error codes that allow retrying
* @param int $retryInterval Seconds to wait before allowing next retry, 0 for no wait.
*/
public function __construct(array $errorCodes, int $retryInterval)
{
$this->errorCodes = $errorCodes;
$this->retryInterval = $retryInterval;
}
/**
* @inheritDoc
*/
public function shouldRetry(Exception $exception, int $retryCount): bool
{
if (
$exception instanceof PDOException &&
$exception->errorInfo &&
in_array($exception->errorInfo[1], $this->errorCodes)
) {
if ($this->retryInterval > 0) {
sleep($this->retryInterval);
}
return true;
}
return false;
}
}
+124
View File
@@ -0,0 +1,124 @@
<?php
declare(strict_types=1);
/**
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
* @link https://cakephp.org CakePHP(tm) Project
* @since 3.6.0
* @license https://opensource.org/licenses/mit-license.php MIT License
*/
namespace Cake\Database\Retry;
use Cake\Core\Retry\RetryStrategyInterface;
use Cake\Database\Connection;
use Exception;
/**
* Makes sure the connection to the database is alive before authorizing
* the retry of an action.
*
* @internal
*/
class ReconnectStrategy implements RetryStrategyInterface
{
/**
* The list of error strings to match when looking for a disconnection error.
*
* This is a static variable to enable opcache to inline the values.
*
* @var array<string>
*/
protected static $causes = [
'gone away',
'Lost connection',
'Transaction() on null',
'closed the connection unexpectedly',
'closed unexpectedly',
'deadlock avoided',
'decryption failed or bad record mac',
'is dead or not enabled',
'no connection to the server',
'query_wait_timeout',
'reset by peer',
'terminate due to client_idle_limit',
'while sending',
'writing data to the connection',
];
/**
* The connection to check for validity
*
* @var \Cake\Database\Connection
*/
protected $connection;
/**
* Creates the ReconnectStrategy object by storing a reference to the
* passed connection. This reference will be used to automatically
* reconnect to the server in case of failure.
*
* @param \Cake\Database\Connection $connection The connection to check
*/
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
/**
* {@inheritDoc}
*
* Checks whether the exception was caused by a lost connection,
* and returns true if it was able to successfully reconnect.
*/
public function shouldRetry(Exception $exception, int $retryCount): bool
{
$message = $exception->getMessage();
foreach (static::$causes as $cause) {
if (strstr($message, $cause) !== false) {
return $this->reconnect();
}
}
return false;
}
/**
* Tries to re-establish the connection to the server, if it is safe to do so
*
* @return bool Whether the connection was re-established
*/
protected function reconnect(): bool
{
if ($this->connection->inTransaction()) {
// It is not safe to blindly reconnect in the middle of a transaction
return false;
}
try {
// Make sure we free any resources associated with the old connection
$this->connection->getDriver()->disconnect();
} catch (Exception $e) {
}
try {
$this->connection->connect();
if ($this->connection->isQueryLoggingEnabled()) {
$this->connection->log('[RECONNECT]');
}
return true;
} catch (Exception $e) {
// If there was an error connecting again, don't report it back,
// let the retry handler do it.
return false;
}
}
}