1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-24 15:23:11 +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 * 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. * 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 * https://processwire.com
* *
* This file is licensed under the MIT license * This file is licensed under the MIT license
@@ -672,7 +672,7 @@ abstract class DatabaseQuery extends WireData {
* *
*/ */
public function prepare() { public function prepare() {
$query = $this->wire('database')->prepare($this->getQuery()); $query = $this->wire()->database->prepare($this->getQuery());
foreach($this->bindValues as $key => $value) { foreach($this->bindValues as $key => $value) {
$type = isset($this->bindTypes[$key]) ? $this->bindTypes[$key] : $this->pdoParamType($value); $type = isset($this->bindTypes[$key]) ? $this->bindTypes[$key] : $this->pdoParamType($value);
$query->bindValue($key, $value, $type); $query->bindValue($key, $value, $type);
@@ -701,22 +701,54 @@ abstract class DatabaseQuery extends WireData {
/** /**
* Execute the query with the current database handle * 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 * @throws WireDatabaseQueryException|\PDOException
* *
*/ */
public function execute() { public function execute(array $options = array()) {
$database = $this->wire('database');
$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 { try {
$query = $this->prepare(); $query = $this->prepare();
$query->execute(); $result = $query->execute();
} catch(\Exception $e) { } catch(\PDOException $e) {
$msg = $e->getMessage(); $msg = $e->getMessage();
if(stripos($msg, 'MySQL server has gone away') !== false) $database->closeConnection(); $code = (int) $e->getCode();
if($this->wire('config')->allowExceptions) throw $e; // throw original $retry = $code === 2006 || stripos($msg, 'MySQL server has gone away') !== false;
throw new WireDatabaseQueryException($msg, $e->getCode(), $e); if($retry && $numTries < $options['maxTries']) {
$this->wire()->database->closeConnection(); // note: it reconnects automatically
$numTries++;
} else {
$exception = $e;
$retry = false;
} }
return $query; }
} while($retry);
if($exception && $options['throw']) {
if($this->wire()->config->allowExceptions) throw $exception; // throw original
throw new WireDatabaseQueryException($exception->getMessage(), $exception->getCode(), $exception);
}
return $options['returnQuery'] ? $query : $result;
} }
} }