Skip to content

Instantly share code, notes, and snippets.

@extraordinaire
Last active June 27, 2023 11:12
Show Gist options
  • Save extraordinaire/4135119 to your computer and use it in GitHub Desktop.
Save extraordinaire/4135119 to your computer and use it in GitHub Desktop.
Reconnectable PDO
<?php
class ReconnectingPDO
{
protected $dsn, $username, $password, $pdo, $driver_options;
public function __construct($dsn, $username = "", $password = "", $driver_options = array())
{
$this->dsn = $dsn;
$this->username = $username;
$this->password = $password;
$this->driver_options = $driver_options;
}
public function __call($name, array $arguments)
{
try {
$this->connection()->query("SHOW STATUS;")->execute();
} catch(\PDOException $e) {
if($e->getCode() != 'HY000' || !stristr($e->getMessage(), 'server has gone away')) {
throw $e;
}
$this->reconnect();
}
return call_user_func_array(array($this->connection(), $name), $arguments);
}
protected function connection()
{
return $this->pdo instanceof \PDO ? $this->pdo : $this->connect();
}
public function connect()
{
$this->pdo = new PDO($this->dsn, $this->username, $this->password, (array) $this->driver_options);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $this->pdo;
}
public function reconnect()
{
$this->pdo = null;
return $this->connect();
}
}
@mindplay-dk
Copy link

In a long-running app, likely the most appropriate thing to do, is don't even attempt to "replay" the query - instead, just throw an exception immediately after reconnecting. Assuming you have an error-handler that can gracefully fail and handle the exception, the current request will fail, but the long-running app itself can continue running and handle the next request.

It's no ideal, but probably only happens if the DB server is down - this at least ensures the long-running app is up and handling requests again as soon as the DB server is back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment