summaryrefslogtreecommitdiffstats
path: root/apps/files_external
diff options
context:
space:
mode:
authorRoeland Jago Douma <rullzer@users.noreply.github.com>2019-03-04 21:36:12 +0100
committerGitHub <noreply@github.com>2019-03-04 21:36:12 +0100
commit243bc96ad9f83034800180813022702d1a550e7c (patch)
tree8a9bd03e891c25d85b65a3d524ea4811333f1e91 /apps/files_external
parenteb175584f64bee35dc1b88b9b3f61db0175b9426 (diff)
parent1ac9a9a1bb0dc6c2d5746cfd4298c185e1267f78 (diff)
downloadnextcloud-server-243bc96ad9f83034800180813022702d1a550e7c.tar.gz
nextcloud-server-243bc96ad9f83034800180813022702d1a550e7c.zip
Merge pull request #14480 from cowai/reconnect-db-notify
Reconnect to DB after timeout for Notify command. Fixes #14479
Diffstat (limited to 'apps/files_external')
-rw-r--r--apps/files_external/lib/Command/Notify.php67
1 files changed, 56 insertions, 11 deletions
diff --git a/apps/files_external/lib/Command/Notify.php b/apps/files_external/lib/Command/Notify.php
index b859a825c80..556687e6930 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 <robin@icewind.nl>
*
+ * @author Ari Selseng <ari@selseng.net>
* @author Robin Appelman <robin@icewind.nl>
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
@@ -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;
@@ -35,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;
@@ -47,17 +50,15 @@ class Notify extends Base {
private $connection;
/** @var \OCP\DB\QueryBuilder\IQueryBuilder */
private $updateQuery;
+ /** @var ILogger */
+ private $logger;
- function __construct(GlobalStoragesService $globalService, IDBConnection $connection) {
+ function __construct(GlobalStoragesService $globalService, IDBConnection $connection, ILogger $logger) {
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->logger = $logger;
+ $this->updateQuery = $this->getUpdateQuery($this->connection);
}
protected function configure() {
@@ -143,9 +144,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 +155,21 @@ 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 $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('<info>Needed to reconnect to the database</info>');
+ $this->updateQuery = $this->getUpdateQuery($this->connection);
+ $this->updateQuery->execute([$parent, $mountId]);
+ }
}
private function logUpdate(IChange $change, OutputInterface $output) {
@@ -188,6 +198,41 @@ 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) {
+ $this->logger->logException($ex, ['app' => 'files_external', 'message' => 'Error while disconnecting from DB', 'level' => ILogger::WARN]);
+ $output->writeln("<info>Error while disconnecting from database: {$ex->getMessage()}</info>");
+ }
+ 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("<info>Error while re-connecting to database: {$ex->getMessage()}</info>");
+ 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');