Merge pull request #54196 from nextcloud/enh/noid/taskprocessing-lazy-config

[TaskProcessing] Load and store some config keys lazily
pull/54241/head
Joas Schilling 2025-08-05 12:28:34 +07:00 committed by GitHub
commit ff3043346a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 34 additions and 40 deletions

@ -12,20 +12,15 @@ use OCA\Settings\Settings\Admin\ArtificialIntelligence;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting;
use OCP\AppFramework\Http\DataResponse;
use OCP\IConfig;
use OCP\IAppConfig;
use OCP\IRequest;
class AISettingsController extends Controller {
/**
* @param string $appName
* @param IRequest $request
* @param IConfig $config
*/
public function __construct(
$appName,
IRequest $request,
private IConfig $config,
private IAppConfig $appConfig,
) {
parent::__construct($appName, $request);
}
@ -43,7 +38,7 @@ class AISettingsController extends Controller {
if (!isset($settings[$key])) {
continue;
}
$this->config->setAppValue('core', $key, json_encode($settings[$key]));
$this->appConfig->setValueString('core', $key, json_encode($settings[$key]), lazy: in_array($key, \OC\TaskProcessing\Manager::LAZY_CONFIG_KEYS, true));
}
return new DataResponse();

@ -10,7 +10,7 @@ namespace OCA\Settings\Settings\Admin;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Services\IInitialState;
use OCP\IConfig;
use OCP\IAppConfig;
use OCP\IL10N;
use OCP\Settings\IDelegatedSettings;
use OCP\SpeechToText\ISpeechToTextManager;
@ -28,7 +28,7 @@ use Psr\Log\LoggerInterface;
class ArtificialIntelligence implements IDelegatedSettings {
public function __construct(
private IConfig $config,
private IAppConfig $appConfig,
private IL10N $l,
private IInitialState $initialState,
private ITranslationManager $translationManager,
@ -145,7 +145,7 @@ class ArtificialIntelligence implements IDelegatedSettings {
];
foreach ($settings as $key => $defaultValue) {
$value = $defaultValue;
$json = $this->config->getAppValue('core', $key, '');
$json = $this->appConfig->getValueString('core', $key, '', lazy: in_array($key, \OC\TaskProcessing\Manager::LAZY_CONFIG_KEYS, true));
if ($json !== '') {
try {
$value = json_decode($json, true, flags: JSON_THROW_ON_ERROR);

@ -2018,11 +2018,6 @@
<code><![CDATA[getSettingsManager]]></code>
</UndefinedInterfaceMethod>
</file>
<file src="apps/settings/lib/Controller/AISettingsController.php">
<DeprecatedMethod>
<code><![CDATA[setAppValue]]></code>
</DeprecatedMethod>
</file>
<file src="apps/settings/lib/Controller/AppSettingsController.php">
<DeprecatedMethod>
<code><![CDATA[getAppValue]]></code>
@ -2083,9 +2078,6 @@
continue;
}]]></code>
</DeprecatedInterface>
<DeprecatedMethod>
<code><![CDATA[getAppValue]]></code>
</DeprecatedMethod>
</file>
<file src="apps/settings/lib/Settings/Admin/Security.php">
<UndefinedInterfaceMethod>
@ -3009,12 +3001,6 @@
<code><![CDATA[resetDelayForIP]]></code>
</DeprecatedMethod>
</file>
<file src="core/Command/TaskProcessing/EnabledCommand.php">
<DeprecatedMethod>
<code><![CDATA[getAppValue]]></code>
<code><![CDATA[setAppValue]]></code>
</DeprecatedMethod>
</file>
<file src="core/Command/Upgrade.php">
<DeprecatedMethod>
<code><![CDATA[listen]]></code>

@ -7,7 +7,7 @@
namespace OC\Core\Command\TaskProcessing;
use OC\Core\Command\Base;
use OCP\IConfig;
use OCP\IAppConfig;
use OCP\TaskProcessing\IManager;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@ -16,7 +16,7 @@ use Symfony\Component\Console\Output\OutputInterface;
class EnabledCommand extends Base {
public function __construct(
protected IManager $taskProcessingManager,
private IConfig $config,
private IAppConfig $appConfig,
) {
parent::__construct();
}
@ -41,7 +41,7 @@ class EnabledCommand extends Base {
protected function execute(InputInterface $input, OutputInterface $output): int {
$enabled = (bool)$input->getArgument('enabled');
$taskType = $input->getArgument('task-type-id');
$json = $this->config->getAppValue('core', 'ai.taskprocessing_type_preferences');
$json = $this->appConfig->getValueString('core', 'ai.taskprocessing_type_preferences', lazy: true);
try {
if ($json === '') {
$taskTypeSettings = [];
@ -51,7 +51,7 @@ class EnabledCommand extends Base {
$taskTypeSettings[$taskType] = $enabled;
$this->config->setAppValue('core', 'ai.taskprocessing_type_preferences', json_encode($taskTypeSettings));
$this->appConfig->setValueString('core', 'ai.taskprocessing_type_preferences', json_encode($taskTypeSettings), lazy: true);
$this->writeArrayInOutputFormat($input, $output, $taskTypeSettings);
return 0;
} catch (\JsonException $e) {

@ -31,9 +31,9 @@ use OCP\Files\Node;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Http\Client\IClientService;
use OCP\IAppConfig;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IL10N;
use OCP\IServerContainer;
use OCP\IUserManager;
@ -73,6 +73,11 @@ class Manager implements IManager {
public const LEGACY_PREFIX_TEXTTOIMAGE = 'legacy:TextToImage:';
public const LEGACY_PREFIX_SPEECHTOTEXT = 'legacy:SpeechToText:';
public const LAZY_CONFIG_KEYS = [
'ai.taskprocessing_type_preferences',
'ai.taskprocessing_provider_preferences',
];
/** @var list<IProvider>|null */
private ?array $providers = null;
@ -92,7 +97,7 @@ class Manager implements IManager {
private ?GetTaskProcessingProvidersEvent $eventResult = null;
public function __construct(
private IConfig $config,
private IAppConfig $appConfig,
private Coordinator $coordinator,
private IServerContainer $serverContainer,
private LoggerInterface $logger,
@ -630,7 +635,7 @@ class Manager implements IManager {
*/
private function _getTaskTypeSettings(): array {
try {
$json = $this->config->getAppValue('core', 'ai.taskprocessing_type_preferences', '');
$json = $this->appConfig->getValueString('core', 'ai.taskprocessing_type_preferences', '', lazy: true);
if ($json === '') {
return [];
}
@ -788,7 +793,11 @@ class Manager implements IManager {
if ($this->preferences === null) {
$this->preferences = $this->distributedCache->get('ai.taskprocessing_provider_preferences');
if ($this->preferences === null) {
$this->preferences = json_decode($this->config->getAppValue('core', 'ai.taskprocessing_provider_preferences', 'null'), associative: true, flags: JSON_THROW_ON_ERROR);
$this->preferences = json_decode(
$this->appConfig->getValueString('core', 'ai.taskprocessing_provider_preferences', 'null', lazy: true),
associative: true,
flags: JSON_THROW_ON_ERROR,
);
$this->distributedCache->set('ai.taskprocessing_provider_preferences', $this->preferences, 60 * 3);
}
}
@ -889,7 +898,7 @@ class Manager implements IManager {
$user = $this->userManager->get($userId);
}
$guestsAllowed = $this->config->getAppValue('core', 'ai.taskprocessing_guests', 'false');
$guestsAllowed = $this->appConfig->getValueString('core', 'ai.taskprocessing_guests', 'false');
if ($guestsAllowed == 'true' || !class_exists(\OCA\Guests\UserBackend::class) || !($user->getBackend() instanceof \OCA\Guests\UserBackend)) {
return true;
}

@ -26,6 +26,7 @@ use OCP\TaskProcessing\Exception\ValidationException;
* @since 30.0.0
*/
interface IManager {
/**
* @since 30.0.0
*/

@ -24,6 +24,7 @@ use OCP\Files\Config\IUserMountCache;
use OCP\Files\File;
use OCP\Files\IRootFolder;
use OCP\Http\Client\IClientService;
use OCP\IAppConfig;
use OCP\ICacheFactory;
use OCP\IConfig;
use OCP\IDBConnection;
@ -535,6 +536,7 @@ class TaskProcessingTest extends \Test\TestCase {
private IUserMountCache $userMountCache;
private IRootFolder $rootFolder;
private IConfig $config;
private IAppConfig $appConfig;
public const TEST_USER = 'testuser';
@ -600,8 +602,9 @@ class TaskProcessingTest extends \Test\TestCase {
$this->userMountCache = $this->createMock(IUserMountCache::class);
$this->config = Server::get(IConfig::class);
$this->appConfig = Server::get(IAppConfig::class);
$this->manager = new Manager(
$this->config,
$this->appConfig,
$this->coordinator,
$this->serverContainer,
Server::get(LoggerInterface::class),
@ -641,7 +644,7 @@ class TaskProcessingTest extends \Test\TestCase {
$taskProcessingTypeSettings = [
TextToText::ID => false,
];
$this->config->setAppValue('core', 'ai.taskprocessing_type_preferences', json_encode($taskProcessingTypeSettings));
$this->appConfig->setValueString('core', 'ai.taskprocessing_type_preferences', json_encode($taskProcessingTypeSettings), lazy: true);
self::assertCount(0, $this->manager->getAvailableTaskTypes());
self::assertCount(1, $this->manager->getAvailableTaskTypes(true));
self::assertTrue($this->manager->hasProviders());
@ -651,7 +654,7 @@ class TaskProcessingTest extends \Test\TestCase {
public function testProviderShouldBeRegisteredAndTaskFailValidation(): void {
$this->config->setAppValue('core', 'ai.taskprocessing_type_preferences', '');
$this->appConfig->setValueString('core', 'ai.taskprocessing_type_preferences', '', lazy: true);
$this->registrationContext->expects($this->any())->method('getTaskProcessingProviders')->willReturn([
new ServiceRegistration('test', BrokenSyncProvider::class)
]);
@ -797,7 +800,7 @@ class TaskProcessingTest extends \Test\TestCase {
$taskProcessingTypeSettings = [
TextToText::ID => true,
];
$this->config->setAppValue('core', 'ai.taskprocessing_type_preferences', json_encode($taskProcessingTypeSettings));
$this->appConfig->setValueString('core', 'ai.taskprocessing_type_preferences', json_encode($taskProcessingTypeSettings), lazy: true);
self::assertCount(1, $this->manager->getAvailableTaskTypes());
@ -1239,7 +1242,7 @@ class TaskProcessingTest extends \Test\TestCase {
private function createManagerInstance(): Manager {
// Clear potentially cached config values if needed
$this->config->deleteAppValue('core', 'ai.taskprocessing_type_preferences');
$this->appConfig->deleteKey('core', 'ai.taskprocessing_type_preferences');
// Re-create Text2ImageManager if its state matters or mocks change
$text2imageManager = new \OC\TextToImage\Manager(
@ -1253,7 +1256,7 @@ class TaskProcessingTest extends \Test\TestCase {
);
return new Manager(
$this->config,
$this->appConfig,
$this->coordinator,
$this->serverContainer,
Server::get(LoggerInterface::class),