From 2e3fa511324cd5b21e470f37c7fba7759ca6df73 Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Fri, 1 Aug 2025 11:56:10 +0200 Subject: [PATCH 1/4] feat(taskprocessing): load and store some config keys lazily Signed-off-by: Julien Veyssier --- .../lib/Controller/AISettingsController.php | 11 +++-------- .../lib/Settings/Admin/ArtificialIntelligence.php | 6 +++--- core/Command/TaskProcessing/EnabledCommand.php | 8 ++++---- lib/private/TaskProcessing/Manager.php | 14 +++++++++----- lib/public/TaskProcessing/IManager.php | 11 +++++++++++ 5 files changed, 30 insertions(+), 20 deletions(-) diff --git a/apps/settings/lib/Controller/AISettingsController.php b/apps/settings/lib/Controller/AISettingsController.php index a3b0a8749871b..c3b4ee8c5718b 100644 --- a/apps/settings/lib/Controller/AISettingsController.php +++ b/apps/settings/lib/Controller/AISettingsController.php @@ -12,20 +12,15 @@ 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 @@ public function update($settings) { 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, \OCP\TaskProcessing\IManager::LAZY_CONFIG_KEYS, true)); } return new DataResponse(); diff --git a/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php b/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php index 78bec73382d58..b4974ffbc779e 100644 --- a/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php +++ b/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php @@ -10,7 +10,7 @@ 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 @@ 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 @@ public function getForm() { ]; foreach ($settings as $key => $defaultValue) { $value = $defaultValue; - $json = $this->config->getAppValue('core', $key, ''); + $json = $this->appConfig->getValueString('core', $key, '', lazy: in_array($key, \OCP\TaskProcessing\IManager::LAZY_CONFIG_KEYS, true)); if ($json !== '') { try { $value = json_decode($json, true, flags: JSON_THROW_ON_ERROR); diff --git a/core/Command/TaskProcessing/EnabledCommand.php b/core/Command/TaskProcessing/EnabledCommand.php index 7195d19a7a475..0d4b831812ce7 100644 --- a/core/Command/TaskProcessing/EnabledCommand.php +++ b/core/Command/TaskProcessing/EnabledCommand.php @@ -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 @@ class EnabledCommand extends Base { public function __construct( protected IManager $taskProcessingManager, - private IConfig $config, + private IAppConfig $appConfig, ) { parent::__construct(); } @@ -41,7 +41,7 @@ protected function configure() { 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 @@ protected function execute(InputInterface $input, OutputInterface $output): int $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) { diff --git a/lib/private/TaskProcessing/Manager.php b/lib/private/TaskProcessing/Manager.php index a9c9f1e1ca223..ab892c1de85f7 100644 --- a/lib/private/TaskProcessing/Manager.php +++ b/lib/private/TaskProcessing/Manager.php @@ -31,9 +31,9 @@ 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; @@ -92,7 +92,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 +630,7 @@ private function _getTaskTypes(): array { */ 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 +788,11 @@ public function getPreferredProvider(string $taskTypeId) { 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 +893,7 @@ private function checkGuestAccess(?string $userId = null): bool { $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; } diff --git a/lib/public/TaskProcessing/IManager.php b/lib/public/TaskProcessing/IManager.php index f161030f5f491..e937917a6cbe1 100644 --- a/lib/public/TaskProcessing/IManager.php +++ b/lib/public/TaskProcessing/IManager.php @@ -26,6 +26,17 @@ * @since 30.0.0 */ interface IManager { + + /** + * Task processing config keys that can be stored and loaded lazily + * + * @since 32.0.0 + */ + public const LAZY_CONFIG_KEYS = [ + 'ai.taskprocessing_type_preferences', + 'ai.taskprocessing_provider_preferences', + ]; + /** * @since 30.0.0 */ From 282bedcfb0fcc223a52f6bf99e57183504e07704 Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Fri, 1 Aug 2025 13:08:14 +0200 Subject: [PATCH 2/4] fix(taskprocessing): remove unused psalm baseline entries Signed-off-by: Julien Veyssier --- build/psalm-baseline.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index 73dfeab49e44d..71eba2ed8560c 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -2018,11 +2018,6 @@ - - - - - @@ -2083,9 +2078,6 @@ continue; }]]> - - - @@ -3010,12 +3002,6 @@ - - - - - - From f22f7311de86080cc9f0f96321e659486d79160b Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Fri, 1 Aug 2025 13:14:10 +0200 Subject: [PATCH 3/4] fix(taskprocessing): fix TaskProcessingTest Signed-off-by: Julien Veyssier --- tests/lib/TaskProcessing/TaskProcessingTest.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/lib/TaskProcessing/TaskProcessingTest.php b/tests/lib/TaskProcessing/TaskProcessingTest.php index db474a006877b..fee4e9ba3bad8 100644 --- a/tests/lib/TaskProcessing/TaskProcessingTest.php +++ b/tests/lib/TaskProcessing/TaskProcessingTest.php @@ -24,6 +24,7 @@ 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 @@ protected function setUp(): void { $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 @@ public function testProviderShouldBeRegisteredAndTaskTypeDisabled(): void { $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 @@ public function testProviderShouldBeRegisteredAndTaskTypeDisabled(): void { 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 @@ public function testTaskTypeExplicitlyEnabled(): void { $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 @@ public function testMergeTaskTypesLocalAndEvent() { 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 @@ private function createManagerInstance(): Manager { ); return new Manager( - $this->config, + $this->appConfig, $this->coordinator, $this->serverContainer, Server::get(LoggerInterface::class), From be7ef439cf92a1447c99727f47be009e7540556d Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Fri, 1 Aug 2025 15:35:56 +0200 Subject: [PATCH 4/4] fix(taskprocessing): move LAZY_CONFIG_KEYS constant to the private namespace Signed-off-by: Julien Veyssier --- apps/settings/lib/Controller/AISettingsController.php | 2 +- .../lib/Settings/Admin/ArtificialIntelligence.php | 2 +- lib/private/TaskProcessing/Manager.php | 5 +++++ lib/public/TaskProcessing/IManager.php | 10 ---------- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/apps/settings/lib/Controller/AISettingsController.php b/apps/settings/lib/Controller/AISettingsController.php index c3b4ee8c5718b..114cbf6151435 100644 --- a/apps/settings/lib/Controller/AISettingsController.php +++ b/apps/settings/lib/Controller/AISettingsController.php @@ -38,7 +38,7 @@ public function update($settings) { if (!isset($settings[$key])) { continue; } - $this->appConfig->setValueString('core', $key, json_encode($settings[$key]), lazy: in_array($key, \OCP\TaskProcessing\IManager::LAZY_CONFIG_KEYS, true)); + $this->appConfig->setValueString('core', $key, json_encode($settings[$key]), lazy: in_array($key, \OC\TaskProcessing\Manager::LAZY_CONFIG_KEYS, true)); } return new DataResponse(); diff --git a/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php b/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php index b4974ffbc779e..aaec0049b206f 100644 --- a/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php +++ b/apps/settings/lib/Settings/Admin/ArtificialIntelligence.php @@ -145,7 +145,7 @@ public function getForm() { ]; foreach ($settings as $key => $defaultValue) { $value = $defaultValue; - $json = $this->appConfig->getValueString('core', $key, '', lazy: in_array($key, \OCP\TaskProcessing\IManager::LAZY_CONFIG_KEYS, true)); + $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); diff --git a/lib/private/TaskProcessing/Manager.php b/lib/private/TaskProcessing/Manager.php index ab892c1de85f7..11fb2bed559e2 100644 --- a/lib/private/TaskProcessing/Manager.php +++ b/lib/private/TaskProcessing/Manager.php @@ -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|null */ private ?array $providers = null; diff --git a/lib/public/TaskProcessing/IManager.php b/lib/public/TaskProcessing/IManager.php index e937917a6cbe1..723eca8f61561 100644 --- a/lib/public/TaskProcessing/IManager.php +++ b/lib/public/TaskProcessing/IManager.php @@ -27,16 +27,6 @@ */ interface IManager { - /** - * Task processing config keys that can be stored and loaded lazily - * - * @since 32.0.0 - */ - public const LAZY_CONFIG_KEYS = [ - 'ai.taskprocessing_type_preferences', - 'ai.taskprocessing_provider_preferences', - ]; - /** * @since 30.0.0 */