1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-12 17:54:44 +02:00

Move DB "MySQL server has gone away" retry logic from WireDatabasePDO into DatabaseQuery, per processwire/processwire-issues#1302

This commit is contained in:
Ryan Cramer
2021-03-29 08:38:56 -04:00
parent 84d7ea797e
commit f98d25b83c

View File

@@ -10,7 +10,7 @@
* of what other methods/objects have done to it. It also means being able
* to build a complex query without worrying about correct syntax placement.
*
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
* https://processwire.com
*
* This file is licensed under the MIT license
@@ -672,7 +672,7 @@ abstract class DatabaseQuery extends WireData {
*
*/
public function prepare() {
$query = $this->wire('database')->prepare($this->getQuery());
$query = $this->wire()->database->prepare($this->getQuery());
foreach($this->bindValues as $key => $value) {
$type = isset($this->bindTypes[$key]) ? $this->bindTypes[$key] : $this->pdoParamType($value);
$query->bindValue($key, $value, $type);
@@ -701,22 +701,54 @@ abstract class DatabaseQuery extends WireData {
/**
* Execute the query with the current database handle
*
* @return \PDOStatement
* @param array $options
* - `throw` (bool): Throw exceptions? (default=true)
* - `maxTries` (int): Max times to retry if connection lost during query. (default=3)
* - `returnQuery` (bool): Return PDOStatement query? If false, returns bool result of execute. (default=true)
* @return \PDOStatement|bool
* @throws WireDatabaseQueryException|\PDOException
*
*/
public function execute() {
$database = $this->wire('database');
try {
$query = $this->prepare();
$query->execute();
} catch(\Exception $e) {
$msg = $e->getMessage();
if(stripos($msg, 'MySQL server has gone away') !== false) $database->closeConnection();
if($this->wire('config')->allowExceptions) throw $e; // throw original
throw new WireDatabaseQueryException($msg, $e->getCode(), $e);
public function execute(array $options = array()) {
$defaults = array(
'throw' => true,
'maxTries' => 3,
'returnQuery' => true,
);
$options = array_merge($defaults, $options);
$numTries = 0;
do {
$retry = false;
$exception = null;
$result = false;
$query = null;
try {
$query = $this->prepare();
$result = $query->execute();
} catch(\PDOException $e) {
$msg = $e->getMessage();
$code = (int) $e->getCode();
$retry = $code === 2006 || stripos($msg, 'MySQL server has gone away') !== false;
if($retry && $numTries < $options['maxTries']) {
$this->wire()->database->closeConnection(); // note: it reconnects automatically
$numTries++;
} else {
$exception = $e;
$retry = false;
}
}
} while($retry);
if($exception && $options['throw']) {
if($this->wire()->config->allowExceptions) throw $exception; // throw original
throw new WireDatabaseQueryException($exception->getMessage(), $exception->getCode(), $exception);
}
return $query;
return $options['returnQuery'] ? $query : $result;
}
}