diff --git a/lib/Alchemy/Phrasea/Command/Setup/Install.php b/lib/Alchemy/Phrasea/Command/Setup/Install.php index e07726088f..49691cf9f4 100644 --- a/lib/Alchemy/Phrasea/Command/Setup/Install.php +++ b/lib/Alchemy/Phrasea/Command/Setup/Install.php @@ -12,7 +12,7 @@ namespace Alchemy\Phrasea\Command\Setup; use Alchemy\Phrasea\Command\Command; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; diff --git a/lib/Alchemy/Phrasea/Controller/Thesaurus/Thesaurus.php b/lib/Alchemy/Phrasea/Controller/Thesaurus/Thesaurus.php index 62677bb1eb..5d3b15670f 100644 --- a/lib/Alchemy/Phrasea/Controller/Thesaurus/Thesaurus.php +++ b/lib/Alchemy/Phrasea/Controller/Thesaurus/Thesaurus.php @@ -11,7 +11,7 @@ namespace Alchemy\Phrasea\Controller\Thesaurus; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; use Silex\Application; use Silex\ControllerProviderInterface; use Symfony\Component\HttpFoundation\Request; diff --git a/lib/Alchemy/Phrasea/Core/Connection/ConnectionProvider.php b/lib/Alchemy/Phrasea/Core/Connection/ConnectionProvider.php index b236201fc2..07000ea6f2 100644 --- a/lib/Alchemy/Phrasea/Core/Connection/ConnectionProvider.php +++ b/lib/Alchemy/Phrasea/Core/Connection/ConnectionProvider.php @@ -13,7 +13,7 @@ namespace Alchemy\Phrasea\Core\Connection; use Doctrine\Common\EventManager; use Doctrine\DBAL\Configuration; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\DriverManager; class ConnectionProvider @@ -58,6 +58,6 @@ class ConnectionProvider return $this->connections[$key]; } - return $this->connections[$key] = DriverManager::getConnection($params, $this->config, $this->eventManager);; + return $this->connections[$key] = new ReconnectableConnection(DriverManager::getConnection($params, $this->config, $this->eventManager)); } } diff --git a/lib/Alchemy/Phrasea/Core/Connection/ReconnectableConnection.php b/lib/Alchemy/Phrasea/Core/Connection/ReconnectableConnection.php new file mode 100644 index 0000000000..185a3ad900 --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Connection/ReconnectableConnection.php @@ -0,0 +1,146 @@ +connection = $connection; + } + + /** + * {@inheritdoc} + */ + function prepare($prepareString) + { + return $this->tryMethod(__FUNCTION__, func_get_args()); + } + + /** + * {@inheritdoc} + */ + function query() + { + return $this->tryMethod(__FUNCTION__, func_get_args()); + } + + /** + * {@inheritdoc} + */ + function quote($input, $type=\PDO::PARAM_STR) + { + return $this->tryMethod(__FUNCTION__, func_get_args()); + } + + /** + * {@inheritdoc} + */ + function exec($statement) + { + return $this->tryMethod(__FUNCTION__, func_get_args()); + } + + /** + * {@inheritdoc} + */ + function lastInsertId($name = null) + { + return $this->tryMethod(__FUNCTION__, func_get_args()); + } + + /** + * {@inheritdoc} + */ + function beginTransaction() + { + return $this->tryMethod(__FUNCTION__, func_get_args()); + } + + /** + * {@inheritdoc} + */ + function commit() + { + return $this->tryMethod(__FUNCTION__, func_get_args()); + } + + /** + * {@inheritdoc} + */ + function rollBack() + { + return $this->tryMethod(__FUNCTION__, func_get_args()); + } + + /** + * {@inheritdoc} + */ + function errorCode() + { + return $this->tryMethod(__FUNCTION__, func_get_args()); + } + + /** + * {@inheritdoc} + */ + function errorInfo() + { + return $this->tryMethod(__FUNCTION__, func_get_args()); + } + + /** + * {@inheritdoc} + */ + public function __call($method, $args) + { + return $this->tryMethod($method, $args); + } + + private function tryMethod($method, $args) + { + try { + set_error_handler(function ($errno, $errstr) { throw new \Exception($errstr, $errno); }); + $ret = call_user_func_array([$this->connection, $method], $args); + restore_error_handler(); + + return $ret; + } catch (\Exception $exception) { + restore_error_handler(); + $e = $exception; + while ($e->getPrevious() && !$e instanceof \PDOException) { + $e = $e->getPrevious(); + } + if ($e instanceof \PDOException && $e->errorInfo[1] == self::MYSQL_CONNECTION_TIMED_WAIT_CODE) { + $this->connection->close(); + $this->connection->connect(); + + return call_user_func_array([$this->connection, $method], $args); + } + if ((false !== strpos($exception->getMessage(), 'MySQL server has gone away')) || (false !== strpos($exception->getMessage(), 'errno=32 Broken pipe'))) { + $this->connection->close(); + $this->connection->connect(); + + return call_user_func_array([$this->connection, $method], $args); + } + + throw $e; + } + } +} diff --git a/lib/Alchemy/Phrasea/Model/Manager/UserManager.php b/lib/Alchemy/Phrasea/Model/Manager/UserManager.php index 6d99f8893a..ea83c62d67 100644 --- a/lib/Alchemy/Phrasea/Model/Manager/UserManager.php +++ b/lib/Alchemy/Phrasea/Model/Manager/UserManager.php @@ -14,7 +14,7 @@ namespace Alchemy\Phrasea\Model\Manager; use Doctrine\Common\Persistence\ObjectManager; use Alchemy\Phrasea\Model\Entities\User; use Alchemy\Phrasea\Model\Entities\UserSetting; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; use Doctrine\ORM\UnitOfWork AS UOW; class UserManager diff --git a/lib/Alchemy/Phrasea/Setup/Installer.php b/lib/Alchemy/Phrasea/Setup/Installer.php index 6b2d6ccb02..40b7600337 100644 --- a/lib/Alchemy/Phrasea/Setup/Installer.php +++ b/lib/Alchemy/Phrasea/Setup/Installer.php @@ -12,7 +12,7 @@ namespace Alchemy\Phrasea\Setup; use Alchemy\Phrasea\Application; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; use Doctrine\DBAL\DBALException; use Doctrine\ORM\Tools\SchemaTool; use Alchemy\Phrasea\Model\Entities\User; diff --git a/lib/classes/base.php b/lib/classes/base.php index b75c35384e..4cd131c7f4 100644 --- a/lib/classes/base.php +++ b/lib/classes/base.php @@ -13,7 +13,7 @@ use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Core\Version as PhraseaVersion; use vierbergenlars\SemVer\version; use Alchemy\Phrasea\Model\Entities\User; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; abstract class base implements cache_cacheableInterface { diff --git a/lib/classes/collection.php b/lib/classes/collection.php index 30d3fa8083..0671c3c417 100644 --- a/lib/classes/collection.php +++ b/lib/classes/collection.php @@ -12,7 +12,7 @@ use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Exception\InvalidArgumentException; use Alchemy\Phrasea\Model\Entities\User; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; class collection implements cache_cacheableInterface { diff --git a/lib/classes/databox.php b/lib/classes/databox.php index 253e7e4fae..8d30cb6ae1 100644 --- a/lib/classes/databox.php +++ b/lib/classes/databox.php @@ -12,7 +12,7 @@ use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Model\Entities\User; use Alchemy\Phrasea\Exception\InvalidArgumentException; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\Translation\TranslatorInterface; diff --git a/lib/classes/databox/field.php b/lib/classes/databox/field.php index f06b546c25..f521ade653 100644 --- a/lib/classes/databox/field.php +++ b/lib/classes/databox/field.php @@ -13,7 +13,7 @@ use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Vocabulary; use Alchemy\Phrasea\Vocabulary\ControlProvider\ControlProviderInterface; use Alchemy\Phrasea\Metadata\Tag\Nosource; -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; use PHPExiftool\Driver\TagInterface; use PHPExiftool\Driver\TagFactory; use PHPExiftool\Exception\TagUnknown; diff --git a/lib/classes/patchthesaurus/100.php b/lib/classes/patchthesaurus/100.php index cf622e9fd1..09934b8b35 100644 --- a/lib/classes/patchthesaurus/100.php +++ b/lib/classes/patchthesaurus/100.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; class patchthesaurus_100 implements patchthesaurus_interface { diff --git a/lib/classes/patchthesaurus/200.php b/lib/classes/patchthesaurus/200.php index bf55ae546e..ca6b3817b9 100644 --- a/lib/classes/patchthesaurus/200.php +++ b/lib/classes/patchthesaurus/200.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; class patchthesaurus_200 implements patchthesaurus_interface { diff --git a/lib/classes/patchthesaurus/201.php b/lib/classes/patchthesaurus/201.php index 33d73c8b7e..95eb641d1d 100644 --- a/lib/classes/patchthesaurus/201.php +++ b/lib/classes/patchthesaurus/201.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; class patchthesaurus_201 implements patchthesaurus_interface { diff --git a/lib/classes/patchthesaurus/202.php b/lib/classes/patchthesaurus/202.php index 61d1d89803..50916c81c6 100644 --- a/lib/classes/patchthesaurus/202.php +++ b/lib/classes/patchthesaurus/202.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; class patchthesaurus_202 implements patchthesaurus_interface { diff --git a/lib/classes/patchthesaurus/203.php b/lib/classes/patchthesaurus/203.php index 19b6573933..6d67ce10f2 100644 --- a/lib/classes/patchthesaurus/203.php +++ b/lib/classes/patchthesaurus/203.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; class patchthesaurus_203 implements patchthesaurus_interface { diff --git a/lib/classes/patchthesaurus/204.php b/lib/classes/patchthesaurus/204.php index d512468d6d..b0a6d547f2 100644 --- a/lib/classes/patchthesaurus/204.php +++ b/lib/classes/patchthesaurus/204.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; class patchthesaurus_204 implements patchthesaurus_interface { diff --git a/lib/classes/patchthesaurus/interface.php b/lib/classes/patchthesaurus/interface.php index e332c477cb..d642861151 100644 --- a/lib/classes/patchthesaurus/interface.php +++ b/lib/classes/patchthesaurus/interface.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver\Connection; interface patchthesaurus_interface { diff --git a/tests/Alchemy/Tests/Phrasea/Command/Setup/InstallTest.php b/tests/Alchemy/Tests/Phrasea/Command/Setup/InstallTest.php index 8229480097..acd1900e56 100644 --- a/tests/Alchemy/Tests/Phrasea/Command/Setup/InstallTest.php +++ b/tests/Alchemy/Tests/Phrasea/Command/Setup/InstallTest.php @@ -84,7 +84,7 @@ class InstallTest extends \PhraseanetTestCase self::$DI['cli']['phraseanet.installer']->expects($this->once()) ->method('install') - ->with($email, $password, $this->isInstanceOf('Doctrine\DBAL\Connection'), $serverName, $dataPath, $this->isInstanceOf('Doctrine\DBAL\Connection'), $template, $this->anything()); + ->with($email, $password, $this->isInstanceOf('Doctrine\DBAL\Driver\Connection'), $serverName, $dataPath, $this->isInstanceOf('Doctrine\DBAL\Driver\Connection'), $template, $this->anything()); $command = new Install('system:check'); $command->setHelperSet($helperSet); diff --git a/tests/Alchemy/Tests/Phrasea/Core/Connection/ConnectionProviderTest.php b/tests/Alchemy/Tests/Phrasea/Core/Connection/ConnectionProviderTest.php new file mode 100644 index 0000000000..73634f5e89 --- /dev/null +++ b/tests/Alchemy/Tests/Phrasea/Core/Connection/ConnectionProviderTest.php @@ -0,0 +1,17 @@ +get(self::$DI['app']['conf']->get(['main', 'database'])); + $conn->exec('SET @@local.wait_timeout= 1'); + usleep(1200000); + $conn->exec('SHOW DATABASES'); + } +} \ No newline at end of file diff --git a/tests/classes/collectionTest.php b/tests/classes/collectionTest.php index 6f7c084618..01bf5b2c22 100644 --- a/tests/classes/collectionTest.php +++ b/tests/classes/collectionTest.php @@ -112,7 +112,7 @@ class collectionTest extends \PhraseanetAuthenticatedTestCase public function testGet_connection() { - $this->assertInstanceOf('Doctrine\DBAL\Connection', self::$object->get_connection()); + $this->assertInstanceOf('Doctrine\DBAL\Driver\Connection', self::$object->get_connection()); } /** diff --git a/tests/classes/databox/fieldTest.php b/tests/classes/databox/fieldTest.php index 09f8927f10..57aaf4294b 100644 --- a/tests/classes/databox/fieldTest.php +++ b/tests/classes/databox/fieldTest.php @@ -70,8 +70,8 @@ class databox_fieldTest extends \PhraseanetTestCase public function testGet_connection() { - $this->assertInstanceOf('Doctrine\DBAL\Connection', $this->object_mono->get_connection()); - $this->assertInstanceOf('Doctrine\DBAL\Connection', $this->object_multi->get_connection()); + $this->assertInstanceOf('Doctrine\DBAL\Driver\Connection', $this->object_mono->get_connection()); + $this->assertInstanceOf('Doctrine\DBAL\Driver\Connection', $this->object_multi->get_connection()); } public function testGet_databox()