Add optional index

This will allow apps to register a handler to provide information about
optional indexes.

Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
This commit is contained in:
Roeland Jago Douma 2021-02-03 22:33:07 +01:00 committed by Arthur Schiwon
parent aa40bdea0f
commit b342a239e7
No known key found for this signature in database
GPG Key ID: 7424F1874854DF23
8 changed files with 241 additions and 2 deletions

View File

@ -110,6 +110,8 @@ class CheckSetupController extends Controller {
private $iniGetWrapper;
/** @var IDBConnection */
private $connection;
/** @var OC\AppFramework\Maintenance\OptionalIndexManager */
private $indexManager;
public function __construct($AppName,
IRequest $request,
@ -126,7 +128,8 @@ class CheckSetupController extends Controller {
MemoryInfo $memoryInfo,
ISecureRandom $secureRandom,
IniGetWrapper $iniGetWrapper,
IDBConnection $connection) {
IDBConnection $connection,
OC\AppFramework\Maintenance\OptionalIndexManager $indexManager) {
parent::__construct($AppName, $request);
$this->config = $config;
$this->clientService = $clientService;
@ -142,6 +145,7 @@ class CheckSetupController extends Controller {
$this->secureRandom = $secureRandom;
$this->iniGetWrapper = $iniGetWrapper;
$this->connection = $connection;
$this->indexManager = $indexManager;
}
/**
@ -466,6 +470,11 @@ Raw output
$event = new GenericEvent($indexInfo);
$this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_INDEXES_EVENT, $event);
$indexes = $this->indexManager->getPending();
foreach ($indexes as $index) {
$indexInfo->addHintForMissingSubject($index->getTable(), $index->getName());
}
return $indexInfo->getListOfMissingIndexes();
}

View File

@ -33,6 +33,7 @@ declare(strict_types=1);
namespace OC\Core\Command\Db;
use OC\AppFramework\Maintenance\OptionalIndexManager;
use OC\DB\Connection;
use OC\DB\SchemaWrapper;
use OCP\IDBConnection;
@ -58,11 +59,17 @@ class AddMissingIndices extends Command {
/** @var EventDispatcherInterface */
private $dispatcher;
public function __construct(Connection $connection, EventDispatcherInterface $dispatcher) {
/** @var OptionalIndexManager */
private $indexManager;
public function __construct(Connection $connection,
EventDispatcherInterface $dispatcher,
OptionalIndexManager $indexManager) {
parent::__construct();
$this->connection = $connection;
$this->dispatcher = $dispatcher;
$this->indexManager = $indexManager;
}
protected function configure() {
@ -77,9 +84,21 @@ class AddMissingIndices extends Command {
// Dispatch event so apps can also update indexes if needed
$event = new GenericEvent($output);
$this->dispatcher->dispatch(IDBConnection::ADD_MISSING_INDEXES_EVENT, $event);
$this->addOptionalIndexed($output);
return 0;
}
private function addOptionalIndexed(OutputInterface $output): void {
$indexes = $this->indexManager->getPending();
foreach ($indexes as $index) {
$output->writeln('<info>Adding additonal ' . $index->getName() . ' index to the ' . $index->getTable() . ' this can take some time..</info>');
$index->add();
}
}
/**
* add missing indices to the share table
*

View File

@ -66,6 +66,7 @@ return array(
'OCP\\AppFramework\\Http\\TooManyRequestsResponse' => $baseDir . '/lib/public/AppFramework/Http/TooManyRequestsResponse.php',
'OCP\\AppFramework\\Http\\ZipResponse' => $baseDir . '/lib/public/AppFramework/Http/ZipResponse.php',
'OCP\\AppFramework\\IAppContainer' => $baseDir . '/lib/public/AppFramework/IAppContainer.php',
'OCP\\AppFramework\\Maintenance\\IOptionalIndex' => $baseDir . '/lib/public/AppFramework/Maintenance/IOptionalIndex.php',
'OCP\\AppFramework\\Middleware' => $baseDir . '/lib/public/AppFramework/Middleware.php',
'OCP\\AppFramework\\OCSController' => $baseDir . '/lib/public/AppFramework/OCSController.php',
'OCP\\AppFramework\\OCS\\OCSBadRequestException' => $baseDir . '/lib/public/AppFramework/OCS/OCSBadRequestException.php',
@ -605,6 +606,7 @@ return array(
'OC\\AppFramework\\Http\\Output' => $baseDir . '/lib/private/AppFramework/Http/Output.php',
'OC\\AppFramework\\Http\\Request' => $baseDir . '/lib/private/AppFramework/Http/Request.php',
'OC\\AppFramework\\Logger' => $baseDir . '/lib/private/AppFramework/Logger.php',
'OC\\AppFramework\\Maintenance\\OptionalIndexManager' => $baseDir . '/lib/private/AppFramework/Maintenance/OptionalIndexManager.php',
'OC\\AppFramework\\Middleware\\AdditionalScriptsMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php',
'OC\\AppFramework\\Middleware\\CompressionMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/CompressionMiddleware.php',
'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => $baseDir . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php',

View File

@ -95,6 +95,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\AppFramework\\Http\\TooManyRequestsResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/TooManyRequestsResponse.php',
'OCP\\AppFramework\\Http\\ZipResponse' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Http/ZipResponse.php',
'OCP\\AppFramework\\IAppContainer' => __DIR__ . '/../../..' . '/lib/public/AppFramework/IAppContainer.php',
'OCP\\AppFramework\\Maintenance\\IOptionalIndex' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Maintenance/IOptionalIndex.php',
'OCP\\AppFramework\\Middleware' => __DIR__ . '/../../..' . '/lib/public/AppFramework/Middleware.php',
'OCP\\AppFramework\\OCSController' => __DIR__ . '/../../..' . '/lib/public/AppFramework/OCSController.php',
'OCP\\AppFramework\\OCS\\OCSBadRequestException' => __DIR__ . '/../../..' . '/lib/public/AppFramework/OCS/OCSBadRequestException.php',
@ -634,6 +635,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\AppFramework\\Http\\Output' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/Output.php',
'OC\\AppFramework\\Http\\Request' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/Request.php',
'OC\\AppFramework\\Logger' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Logger.php',
'OC\\AppFramework\\Maintenance\\OptionalIndexManager' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Maintenance/OptionalIndexManager.php',
'OC\\AppFramework\\Middleware\\AdditionalScriptsMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php',
'OC\\AppFramework\\Middleware\\CompressionMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/CompressionMiddleware.php',
'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php',

View File

@ -34,6 +34,7 @@ use Closure;
use OC\Support\CrashReport\Registry;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\AppFramework\Maintenance\IOptionalIndex;
use OCP\AppFramework\Middleware;
use OCP\AppFramework\Services\InitialStateProvider;
use OCP\Authentication\IAlternativeLogin;
@ -94,6 +95,9 @@ class RegistrationContext {
/** @var ServiceRegistration<INotifier>[] */
private $notifierServices = [];
/** @var ServiceRegistration<IOptionalIndex> */
private $optionalIndexes = [];
/** @var ServiceRegistration<\OCP\Authentication\TwoFactorAuth\IProvider>[] */
private $twoFactorProviders = [];
@ -221,6 +225,13 @@ class RegistrationContext {
);
}
public function registerOptionalIndex(string $class): void {
$this->context->registerOptionalIndex(
$this->appId,
$class
);
}
public function registerTwoFactorProvider(string $twoFactorProviderClass): void {
$this->context->registerTwoFactorProvider(
$this->appId,
@ -284,6 +295,7 @@ class RegistrationContext {
public function registerInitialState(string $appId, string $class): void {
$this->initialStates[] = new ServiceRegistration($appId, $class);
}
public function registerWellKnown(string $appId, string $class): void {
@ -298,6 +310,10 @@ class RegistrationContext {
$this->notifierServices[] = new ServiceRegistration($appId, $class);
}
public function registerOptionalIndex(string $appId, string $class): void {
$this->optionalIndexes[] = new ServiceRegistration($appId, $class);
}
public function registerTwoFactorProvider(string $appId, string $class): void {
$this->twoFactorProviders[] = new ServiceRegistration($appId, $class);
}
@ -315,6 +331,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during capability registration of $appId: " . $e->getMessage(), [
'exception' => $e,
]);
}
}
@ -331,6 +348,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during crash reporter registration of $appId: " . $e->getMessage(), [
'exception' => $e,
]);
}
}
@ -347,6 +365,7 @@ class RegistrationContext {
$appId = $panel->getAppId();
$this->logger->error("Error during dashboard registration of $appId: " . $e->getMessage(), [
'exception' => $e,
]);
}
}
@ -364,6 +383,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during event listener registration of $appId: " . $e->getMessage(), [
'exception' => $e,
]);
}
}
@ -389,6 +409,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during service registration of $appId: " . $e->getMessage(), [
'exception' => $e,
]);
}
}
@ -405,6 +426,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during service alias registration of $appId: " . $e->getMessage(), [
'exception' => $e,
]);
}
}
@ -421,6 +443,7 @@ class RegistrationContext {
$appId = $registration->getAppId();
$this->logger->error("Error during service alias registration of $appId: " . $e->getMessage(), [
'exception' => $e,
]);
}
}
@ -439,6 +462,7 @@ class RegistrationContext {
$appId = $middleware->getAppId();
$this->logger->error("Error during capability registration of $appId: " . $e->getMessage(), [
'exception' => $e,
]);
}
}
@ -486,6 +510,13 @@ class RegistrationContext {
return $this->notifierServices;
}
/**
* @return ServiceRegistration<IOptionalIndex>[]
*/
public function getOptionalIndexes(): array {
return $this->optionalIndexes;
}
/**
* @return ServiceRegistration<\OCP\Authentication\TwoFactorAuth\IProvider>[]
*/
@ -493,3 +524,4 @@ class RegistrationContext {
return $this->twoFactorProviders;
}
}

View File

@ -0,0 +1,92 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2021 Roeland Jago Douma <roeland@famdouma.nl>
*
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* 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
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\AppFramework\Maintenance;
use OC\AppFramework\Bootstrap\Coordinator;
use OCP\AppFramework\Maintenance\IOptionalIndex;
use OCP\AppFramework\QueryException;
use OCP\IServerContainer;
use Psr\Log\LoggerInterface;
class OptionalIndexManager {
/** @var IServerContainer */
private $serverContainer;
/** @var Coordinator */
private $coordinator;
/** @var LoggerInterface */
private $logger;
/** @var IOptionalIndex[] */
private $optionalIndexes;
public function __construct(
IServerContainer $serverContainer,
Coordinator $coordinator,
LoggerInterface $logger
) {
$this->coordinator = $coordinator;
$this->serverContainer = $serverContainer;
$this->logger = $logger;
}
/**
* @return IOptionalIndex[]
*/
public function getPending(): array {
if ($this->optionalIndexes !== null) {
return $this->optionalIndexes;
}
$context = $this->coordinator->getRegistrationContext();
foreach ($context->getOptionalIndexes() as $optionalIndex) {
try {
$class = $this->serverContainer->query($optionalIndex->getService());
} catch (QueryException $e) {
$this->logger->info('Could not initialize ' . $optionalIndex->getService() . ' for ' . $optionalIndex->getAppId());
continue;
}
if (!($class instanceof IOptionalIndex)) {
$this->logger->info($optionalIndex->getService() . ' is not an instance of ' . IOptionalIndex::class);
continue;
}
if ($class->exists()) {
$this->logger->debug($optionalIndex->getService() . ' is already added');
continue;
}
$this->optionalIndexes[] = $class;
}
return $this->optionalIndexes;
}
}

View File

@ -32,6 +32,7 @@ namespace OCP\AppFramework\Bootstrap;
use OCP\AppFramework\IAppContainer;
use OCP\Authentication\TwoFactorAuth\IProvider;
use OCP\Capabilities\ICapability;
use OCP\AppFramework\Maintenance\IOptionalIndex;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Template\ICustomTemplateProvider;
use OCP\IContainer;
@ -221,6 +222,15 @@ interface IRegistrationContext {
*/
public function registerNotifierService(string $notifierClass): void;
/**
* Register an optional index that is able to display and add indexes to the system
*
* @param string $class
* @psalm-param class-string<IOptionalIndex> $class
* @since 22.0.0
*/
public function registerOptionalIndex(string $class): void;
/**
* Register a two-factor provider
*
@ -230,3 +240,4 @@ interface IRegistrationContext {
*/
public function registerTwoFactorProvider(string $twoFactorProviderClass): void;
}

View File

@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2021 Roeland Jago Douma <roeland@famdouma.nl>
*
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* 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
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCP\AppFramework\Maintenance;
/**
* @since 22.0.0
*/
interface IOptionalIndex {
/**
* Get the name of the optional index to display
*
* @since 22.0.0
* @return string
*/
public function getName(): string;
/**
* Get the name of the table this operates on
*
* @since 22.0.0
* @return string
*/
public function getTable(): string;
/**
* Does the optional index already exist
*
* @since 22.0.0
* @return bool
*/
public function exists(): bool;
/**
* Adds the index
*
* @since 22.0.0
*/
public function add(): void;
/**
* Get the SQL for the index creation so we can display this for admins
* to run the queries directly on their DB
*
* @since 22.0.0
* @return string
*/
public function getSQL(): string;
}