From 71a0cdceaaad76cd08f48c28d3da40d7fc8d2abf Mon Sep 17 00:00:00 2001 From: Ari Selseng Date: Sun, 3 Mar 2019 01:36:27 +0100 Subject: Reconnect to DB after timeout for Notify command. Fixes #14479 Signed-off-by: Ari Selseng --- apps/files_external/lib/Command/Notify.php | 58 ++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/apps/files_external/lib/Command/Notify.php b/apps/files_external/lib/Command/Notify.php index b859a825c80..a0b116f07d9 100644 --- a/apps/files_external/lib/Command/Notify.php +++ b/apps/files_external/lib/Command/Notify.php @@ -2,6 +2,7 @@ /** * @copyright Copyright (c) 2016 Robin Appelman * + * @author Ari Selseng * @author Robin Appelman * @author Roeland Jago Douma * @@ -24,6 +25,7 @@ namespace OCA\Files_External\Command; +use Doctrine\DBAL\Exception\DriverException; use OC\Core\Command\Base; use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException; use OCA\Files_External\Lib\StorageConfig; @@ -52,12 +54,7 @@ class Notify extends Base { parent::__construct(); $this->globalService = $globalService; $this->connection = $connection; - // the query builder doesn't really like subqueries with parameters - $this->updateQuery = $this->connection->prepare( - 'UPDATE *PREFIX*filecache SET size = -1 - WHERE `path` = ? - AND `storage` IN (SELECT storage_id FROM *PREFIX*mounts WHERE mount_id = ?)' - ); + $this->updateQuery = $this->getUpdateQuery($this->connection); } protected function configure() { @@ -143,9 +140,9 @@ class Notify extends Base { $this->logUpdate($change, $output); } if ($change instanceof IRenameChange) { - $this->markParentAsOutdated($mount->getId(), $change->getTargetPath()); + $this->markParentAsOutdated($mount->getId(), $change->getTargetPath(), $output); } - $this->markParentAsOutdated($mount->getId(), $change->getPath()); + $this->markParentAsOutdated($mount->getId(), $change->getPath(), $output); }); } @@ -154,12 +151,20 @@ class Notify extends Base { return new $class($mount->getBackendOptions()); } - private function markParentAsOutdated($mountId, $path) { + private function markParentAsOutdated($mountId, $path, OutputInterface $output) { $parent = ltrim(dirname($path), '/'); if ($parent === '.') { $parent = ''; } - $this->updateQuery->execute([$parent, $mountId]); + + try { + $this->updateQuery->execute([$parent, $mountId]); + } catch (DriverException $th) { + $this->connection = $this->reconnectToDatabase($this->connection, $output); + $output->writeln('Needed to reconnect to the database'); + $this->updateQuery = $this->getUpdateQuery($this->connection); + $this->updateQuery->execute([$parent, $mountId]); + } } private function logUpdate(IChange $change, OutputInterface $output) { @@ -188,6 +193,39 @@ class Notify extends Base { $output->writeln($text); } + /** + * @return \Doctrine\DBAL\Statement + */ + private function getUpdateQuery(IDBConnection $connection) { + // the query builder doesn't really like subqueries with parameters + return $connection->prepare( + 'UPDATE *PREFIX*filecache SET size = -1 + WHERE `path` = ? + AND `storage` IN (SELECT storage_id FROM *PREFIX*mounts WHERE mount_id = ?)' + ); + } + + /** + * @return \OCP\IDBConnection + */ + private function reconnectToDatabase(IDBConnection $connection, OutputInterface $output) { + try { + $connection->close(); + } catch (\Exception $ex) { + $output->writeln("Error while disconnecting from database: {$ex->getMessage()}"); + } + while (!$connection->isConnected()) { + try { + $connection->connect(); + } catch (\Exception $ex) { + $output->writeln("Error while re-connecting to database: {$ex->getMessage()}"); + sleep(60); + } + } + return $connection; + } + + private function selfTest(IStorage $storage, INotifyHandler $notifyHandler, $verbose, OutputInterface $output) { usleep(100 * 1000); //give time for the notify to start $storage->file_put_contents('/.nc_test_file.txt', 'test content'); -- cgit v1.2.3 From 3218e0f70de6ad5b4ec6de00f693b2bbbd22f9d7 Mon Sep 17 00:00:00 2001 From: Ari Selseng Date: Mon, 4 Mar 2019 13:54:52 +0100 Subject: Added logging to Notify command. Signed-off-by: Ari Selseng --- apps/files_external/lib/Command/Notify.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/files_external/lib/Command/Notify.php b/apps/files_external/lib/Command/Notify.php index a0b116f07d9..e3ec2e874ae 100644 --- a/apps/files_external/lib/Command/Notify.php +++ b/apps/files_external/lib/Command/Notify.php @@ -37,6 +37,7 @@ use OCP\Files\Storage\INotifyStorage; use OCP\Files\Storage\IStorage; use OCP\Files\StorageNotAvailableException; use OCP\IDBConnection; +use OCP\ILogger; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -49,11 +50,14 @@ class Notify extends Base { private $connection; /** @var \OCP\DB\QueryBuilder\IQueryBuilder */ private $updateQuery; + /** @var ILogger */ + private $log; - function __construct(GlobalStoragesService $globalService, IDBConnection $connection) { + function __construct(GlobalStoragesService $globalService, IDBConnection $connection, ILogger $logger) { parent::__construct(); $this->globalService = $globalService; $this->connection = $connection; + $this->logger = $logger; $this->updateQuery = $this->getUpdateQuery($this->connection); } @@ -159,7 +163,8 @@ class Notify extends Base { try { $this->updateQuery->execute([$parent, $mountId]); - } catch (DriverException $th) { + } catch (DriverException $ex) { + $this->logger->logException($ex, ['app' => 'files_external', 'message' => 'Error while trying to mark folder as outdated', 'level' => ILogger::WARN]); $this->connection = $this->reconnectToDatabase($this->connection, $output); $output->writeln('Needed to reconnect to the database'); $this->updateQuery = $this->getUpdateQuery($this->connection); @@ -212,12 +217,14 @@ class Notify extends Base { try { $connection->close(); } catch (\Exception $ex) { + $this->logger->logException($ex, ['app' => 'files_external', 'message' => 'Error while disconnecting from DB', 'level' => ILogger::WARN]); $output->writeln("Error while disconnecting from database: {$ex->getMessage()}"); } while (!$connection->isConnected()) { try { $connection->connect(); } catch (\Exception $ex) { + $this->logger->logException($ex, ['app' => 'files_external', 'message' => 'Error while re-connecting to database', 'level' => ILogger::WARN]); $output->writeln("Error while re-connecting to database: {$ex->getMessage()}"); sleep(60); } -- cgit v1.2.3 From 1ac9a9a1bb0dc6c2d5746cfd4298c185e1267f78 Mon Sep 17 00:00:00 2001 From: Ari Selseng Date: Mon, 4 Mar 2019 15:02:15 +0100 Subject: Correct log attribute Signed-off-by: Ari Selseng --- apps/files_external/lib/Command/Notify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_external/lib/Command/Notify.php b/apps/files_external/lib/Command/Notify.php index e3ec2e874ae..556687e6930 100644 --- a/apps/files_external/lib/Command/Notify.php +++ b/apps/files_external/lib/Command/Notify.php @@ -51,7 +51,7 @@ class Notify extends Base { /** @var \OCP\DB\QueryBuilder\IQueryBuilder */ private $updateQuery; /** @var ILogger */ - private $log; + private $logger; function __construct(GlobalStoragesService $globalService, IDBConnection $connection, ILogger $logger) { parent::__construct(); -- cgit v1.2.3