Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>tags/v25.0.0beta4
@@ -33,11 +33,13 @@ | |||
*/ | |||
namespace OC\Core\Command; | |||
use OCP\EventDispatcher\IEventDispatcher; | |||
use OCP\IConfig; | |||
use OCP\Util; | |||
use OC\Console\TimestampFormatter; | |||
use OC\DB\MigratorExecuteSqlEvent; | |||
use OC\Installer; | |||
use OC\Updater; | |||
use OCP\IConfig; | |||
use OCP\Util; | |||
use Psr\Log\LoggerInterface; | |||
use Symfony\Component\Console\Command\Command; | |||
use Symfony\Component\Console\Helper\ProgressBar; | |||
@@ -93,28 +95,28 @@ class Upgrade extends Command { | |||
); | |||
$dispatcher = \OC::$server->getEventDispatcher(); | |||
/** @var IEventDispatcher $newDispatcher */ | |||
$newDispatcher = \OC::$server->get(IEventDispatcher::class); | |||
$progress = new ProgressBar($output); | |||
$progress->setFormat(" %message%\n %current%/%max% [%bar%] %percent:3s%%"); | |||
$listener = function ($event) use ($progress, $output) { | |||
if ($event instanceof GenericEvent) { | |||
$message = $event->getSubject(); | |||
if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) { | |||
$output->writeln(' Checking table ' . $message); | |||
} else { | |||
if (strlen($message) > 60) { | |||
$message = substr($message, 0, 57) . '...'; | |||
} | |||
$progress->setMessage($message); | |||
if ($event['step'] === 1) { | |||
$output->writeln(''); | |||
$progress->start($event['max']); | |||
} | |||
$progress->setProgress($event['step']); | |||
if ($event['step'] === $event['max']) { | |||
$progress->setMessage('Done'); | |||
$progress->finish(); | |||
$output->writeln(''); | |||
} | |||
$listener = function (MigratorExecuteSqlEvent $event) use ($progress, $output) { | |||
$message = $event->getSql(); | |||
if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) { | |||
$output->writeln(' Executing SQL ' . $message); | |||
} else { | |||
if (strlen($message) > 60) { | |||
$message = substr($message, 0, 57) . '...'; | |||
} | |||
$progress->setMessage($message); | |||
if ($event->getCurrentStep() === 1) { | |||
$output->writeln(''); | |||
$progress->start($event->getMaxStep()); | |||
} | |||
$progress->setProgress($event->getCurrentStep()); | |||
if ($event->getCurrentStep() === $event->getMaxStep()) { | |||
$progress->setMessage('Done'); | |||
$progress->finish(); | |||
$output->writeln(''); | |||
} | |||
} | |||
}; | |||
@@ -161,7 +163,7 @@ class Upgrade extends Command { | |||
} | |||
}; | |||
$dispatcher->addListener('\OC\DB\Migrator::executeSql', $listener); | |||
$newDispatcher->addListener(MigratorExecuteSqlEvent::class, $listener); | |||
$dispatcher->addListener('\OC\Repair::startProgress', $repairListener); | |||
$dispatcher->addListener('\OC\Repair::advance', $repairListener); | |||
$dispatcher->addListener('\OC\Repair::finishProgress', $repairListener); |
@@ -30,9 +30,11 @@ | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
use OCP\EventDispatcher\IEventDispatcher; | |||
use OCP\IEventSource; | |||
use OCP\IL10N; | |||
use OCP\ILogger; | |||
use OC\DB\MigratorExecuteSqlEvent; | |||
use Symfony\Component\EventDispatcher\GenericEvent; | |||
if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) { | |||
@@ -123,10 +125,10 @@ if (\OCP\Util::needUpgrade()) { | |||
$incompatibleApps = []; | |||
$dispatcher = \OC::$server->getEventDispatcher(); | |||
$dispatcher->addListener('\OC\DB\Migrator::executeSql', function ($event) use ($eventSource, $l) { | |||
if ($event instanceof GenericEvent) { | |||
$eventSource->send('success', $l->t('[%d / %d]: %s', [$event['step'], $event['max'], $event->getSubject()])); | |||
} | |||
/** @var IEventDispatcher $newDispatcher */ | |||
$newDispatcher = \OC::$server->get(IEventDispatcher::class); | |||
$newDispatcher->addListener(MigratorExecuteSqlEvent::class, function (MigratorExecuteSqlEvent $event) use ($eventSource, $l) { | |||
$eventSource->send('success', $l->t('[%d / %d]: %s', [$event->getCurrentStep(), $event->getMaxStep(), $event->getSql()])); | |||
}); | |||
$feedBack = new FeedBackHandler($eventSource, $l); | |||
$dispatcher->addListener('\OC\Repair::startProgress', [$feedBack, 'handleRepairFeedback']); |
@@ -1061,6 +1061,7 @@ return array( | |||
'OC\\DB\\MigrationException' => $baseDir . '/lib/private/DB/MigrationException.php', | |||
'OC\\DB\\MigrationService' => $baseDir . '/lib/private/DB/MigrationService.php', | |||
'OC\\DB\\Migrator' => $baseDir . '/lib/private/DB/Migrator.php', | |||
'OC\\DB\\MigratorExecuteSqlEvent' => $baseDir . '/lib/private/DB/MigratorExecuteSqlEvent.php', | |||
'OC\\DB\\MissingColumnInformation' => $baseDir . '/lib/private/DB/MissingColumnInformation.php', | |||
'OC\\DB\\MissingIndexInformation' => $baseDir . '/lib/private/DB/MissingIndexInformation.php', | |||
'OC\\DB\\MissingPrimaryKeyInformation' => $baseDir . '/lib/private/DB/MissingPrimaryKeyInformation.php', |
@@ -1094,6 +1094,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 | |||
'OC\\DB\\MigrationException' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationException.php', | |||
'OC\\DB\\MigrationService' => __DIR__ . '/../../..' . '/lib/private/DB/MigrationService.php', | |||
'OC\\DB\\Migrator' => __DIR__ . '/../../..' . '/lib/private/DB/Migrator.php', | |||
'OC\\DB\\MigratorExecuteSqlEvent' => __DIR__ . '/../../..' . '/lib/private/DB/MigratorExecuteSqlEvent.php', | |||
'OC\\DB\\MissingColumnInformation' => __DIR__ . '/../../..' . '/lib/private/DB/MissingColumnInformation.php', | |||
'OC\\DB\\MissingIndexInformation' => __DIR__ . '/../../..' . '/lib/private/DB/MissingIndexInformation.php', | |||
'OC\\DB\\MissingPrimaryKeyInformation' => __DIR__ . '/../../..' . '/lib/private/DB/MissingPrimaryKeyInformation.php', |
@@ -37,9 +37,8 @@ use Doctrine\DBAL\Schema\SchemaDiff; | |||
use Doctrine\DBAL\Types\StringType; | |||
use Doctrine\DBAL\Types\Type; | |||
use OCP\IConfig; | |||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||
use Symfony\Component\EventDispatcher\GenericEvent; | |||
use function preg_match; | |||
use OCP\EventDispatcher\IEventDispatcher; | |||
class Migrator { | |||
@@ -49,15 +48,14 @@ class Migrator { | |||
/** @var IConfig */ | |||
protected $config; | |||
/** @var ?EventDispatcherInterface */ | |||
private $dispatcher; | |||
private ?IEventDispatcher $dispatcher; | |||
/** @var bool */ | |||
private $noEmit = false; | |||
public function __construct(Connection $connection, | |||
IConfig $config, | |||
?EventDispatcherInterface $dispatcher = null) { | |||
?IEventDispatcher $dispatcher = null) { | |||
$this->connection = $connection; | |||
$this->config = $config; | |||
$this->dispatcher = $dispatcher; | |||
@@ -183,13 +181,13 @@ class Migrator { | |||
return '/^' . preg_quote($this->config->getSystemValue('dbtableprefix', 'oc_')) . '/'; | |||
} | |||
protected function emit($sql, $step, $max) { | |||
protected function emit(string $sql, int $step, int $max): void { | |||
if ($this->noEmit) { | |||
return; | |||
} | |||
if (is_null($this->dispatcher)) { | |||
return; | |||
} | |||
$this->dispatcher->dispatch('\OC\DB\Migrator::executeSql', new GenericEvent($sql, ['step' => $step + 1, 'max' => $max])); | |||
$this->dispatcher->dispatchTyped(new MigratorExecuteSqlEvent($sql, $step, $max)); | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
<?php | |||
/** | |||
* @copyright Copyright (c) 2022 Côme Chilliet <come.chilliet@nextcloud.com> | |||
* | |||
* @author Côme Chilliet <come.chilliet@nextcloud.com> | |||
* | |||
* @license AGPL-3.0 | |||
* | |||
* This code is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3, | |||
* as published by the Free Software Foundation. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Affero General Public License, version 3, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/> | |||
* | |||
*/ | |||
namespace OC\DB; | |||
use OCP\EventDispatcher\Event; | |||
class MigratorExecuteSqlEvent extends Event { | |||
private string $sql; | |||
private int $current; | |||
private int $max; | |||
public function __construct( | |||
string $sql, | |||
int $current, | |||
int $max, | |||
) { | |||
$this->sql = $sql; | |||
$this->current = $current; | |||
$this->max = $max; | |||
} | |||
public function getSql(): string { | |||
return $this->sql; | |||
} | |||
public function getCurrentStep(): int { | |||
return $this->current; | |||
} | |||
public function getMaxStep(): int { | |||
return $this->max; | |||
} | |||
} |
@@ -463,12 +463,14 @@ class Updater extends BasicEmitter { | |||
$log = $this->log; | |||
$dispatcher = \OC::$server->getEventDispatcher(); | |||
$dispatcher->addListener('\OC\DB\Migrator::executeSql', function ($event) use ($log) { | |||
if (!$event instanceof GenericEvent) { | |||
return; | |||
/** @var IEventDispatcher $newDispatcher */ | |||
$newDispatcher = \OC::$server->get(IEventDispatcher::class); | |||
$newDispatcher->addListener( | |||
MigratorExecuteSqlEvent::class, | |||
function (MigratorExecuteSqlEvent $event) use ($log) { | |||
$log->info(get_class($event).': ' . $event->getSql() . ' (' . $event->getCurrentStep() . ' of ' . $event->getMaxStep() . ')', ['app' => 'updater']); | |||
} | |||
$log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument('step') . ' of ' . $event->getArgument('max') . ')', ['app' => 'updater']); | |||
}); | |||
); | |||
$repairListener = function ($event) use ($log) { | |||
if (!$event instanceof GenericEvent) { |
@@ -62,7 +62,7 @@ class MigratorTest extends \Test\TestCase { | |||
private function getMigrator(): Migrator { | |||
$platform = $this->connection->getDatabasePlatform(); | |||
$random = \OC::$server->getSecureRandom(); | |||
$dispatcher = \OC::$server->getEventDispatcher(); | |||
$dispatcher = \OC::$server->get(\OCP\EventDispatcher\IEventDispatcher::class); | |||
if ($platform instanceof SqlitePlatform) { | |||
return new SQLiteMigrator($this->connection, $this->config, $dispatcher); | |||
} elseif ($platform instanceof OraclePlatform) { |