feat: add new IRepairStepExpensive interface

Expensive repair steps are non-critical repair steps that might take a long time to execute.
Non-critical means that they are not required to directly be executed during migration to have a working instance,
but they might be required to have a fully working instance later on.

Expensive repair steps are only executed when explicitly requested by the administrator.

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
Ferdinand Thiessen 2026-04-27 19:28:36 +02:00
parent d3534595da
commit a974d00571
No known key found for this signature in database
GPG key ID: 7E849AE05218500F
3 changed files with 49 additions and 35 deletions

View file

@ -51,14 +51,11 @@ class Repair extends Command {
}
protected function execute(InputInterface $input, OutputInterface $output): int {
$repairSteps = $this->repair::getRepairSteps();
if ($input->getOption('include-expensive')) {
$repairSteps = array_merge($repairSteps, $this->repair::getExpensiveRepairSteps());
}
$includeExpensive = (bool)$input->getOption('include-expensive');
$repairSteps = $this->repair::getRepairSteps($includeExpensive);
foreach ($repairSteps as $step) {
$this->repair->addStep($step);
$this->repair->addStep($step, $includeExpensive);
}
$apps = $this->appManager->getEnabledApps();
@ -74,7 +71,7 @@ class Repair extends Command {
$steps = $info['repair-steps']['post-migration'];
foreach ($steps as $step) {
try {
$this->repair->addStep($step);
$this->repair->addStep($step, $includeExpensive);
} catch (Exception $ex) {
$output->writeln("<error>Failed to load repair step for $app: {$ex->getMessage()}</error>");
}

View file

@ -64,6 +64,7 @@ use OCP\IConfig;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
use OCP\Migration\IRepairStepExpensive;
use OCP\Server;
use Psr\Container\ContainerExceptionInterface;
use Psr\Log\LoggerInterface;
@ -113,10 +114,11 @@ class Repair implements IOutput {
/**
* Add repair step
*
* @param IRepairStep|class-string<IRepairStep> $repairStep repair step
* @param IRepairStep|class-string<IRepairStep> $repairStep Repair step
* @param bool $includeExpensive Whether to include expensive repair steps, defaults to false
* @throws \Exception
*/
public function addStep(IRepairStep|string $repairStep): void {
public function addStep(IRepairStep|string $repairStep, bool $includeExpensive = false): void {
if (is_string($repairStep)) {
try {
$s = Server::get($repairStep);
@ -134,24 +136,30 @@ class Repair implements IOutput {
}
}
if ($s instanceof IRepairStep) {
$this->repairSteps[] = $s;
} else {
if (!($s instanceof IRepairStep)) {
throw new \Exception("Repair step '$repairStep' is not of type \\OCP\\Migration\\IRepairStep");
}
$repairStep = $s;
}
if (($repairStep instanceof IRepairStepExpensive) && !$includeExpensive) {
$this->debug("Skipping expensive repair step '" . $repairStep::class . "'");
} else {
$this->repairSteps[] = $repairStep;
}
}
/**
* Returns the default repair steps to be run on the
* command line or after an upgrade.
* Returns the core repair steps to be run on the command line or after an upgrade.
*
* @param bool $includeExpensive Whether to include expensive repair steps, defaults to false
* @return list<IRepairStep>
*
* @since 34.0.0, the $includeExpensive parameter was added
*/
public static function getRepairSteps(): array {
return [
public static function getRepairSteps(bool $includeExpensive = false): array {
$repairSteps = [
new Collation(Server::get(IConfig::class), Server::get(LoggerInterface::class), Server::get(IDBConnection::class), false),
Server::get(CleanTags::class),
Server::get(RepairInvalidShares::class),
@ -190,28 +198,17 @@ class Repair implements IOutput {
Server::get(AddMovePreviewJob::class),
Server::get(ConfigKeyMigration::class),
];
}
/**
* Returns expensive repair steps to be run on the
* command line with a special option.
*
* @return list<IRepairStep>
*/
public static function getExpensiveRepairSteps(): array {
$expensiveSteps = [
Server::get(OldGroupMembershipShares::class),
Server::get(RemoveBrokenProperties::class),
Server::get(RepairMimeTypes::class),
Server::get(DeleteSchedulingObjects::class),
Server::get(RemoveObjectProperties::class),
];
if (class_exists(CleanupShareTarget::class)) {
$expensiveSteps[] = Server::get(CleanupShareTarget::class);
if ($includeExpensive) {
$expensiveSteps = [
Server::get(OldGroupMembershipShares::class),
Server::get(RemoveBrokenProperties::class),
Server::get(RepairMimeTypes::class),
];
$repairSteps = array_merge($repairSteps, $expensiveSteps);
}
return $expensiveSteps;
return $repairSteps;
}
/**

View file

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
/*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCP\Migration;
/**
* Expensive repair steps are non-critical repair steps that might take a long time to execute.
* Non-critical means that they are not required to directly be executed during migration to have a working instance,
* but they might be required to have a fully working instance later on.
*
* Expensive repair steps are only executed when explicitly requested by the administrator.
*
* @since 34.0.0
*/
interface IRepairStepExpensive extends IRepairStep {
}