aboutsummaryrefslogtreecommitdiffstats
path: root/core/Command/TaskProcessing
diff options
context:
space:
mode:
Diffstat (limited to 'core/Command/TaskProcessing')
-rw-r--r--core/Command/TaskProcessing/EnabledCommand.php62
-rw-r--r--core/Command/TaskProcessing/GetCommand.php42
-rw-r--r--core/Command/TaskProcessing/ListCommand.php96
-rw-r--r--core/Command/TaskProcessing/Statistics.php194
4 files changed, 394 insertions, 0 deletions
diff --git a/core/Command/TaskProcessing/EnabledCommand.php b/core/Command/TaskProcessing/EnabledCommand.php
new file mode 100644
index 00000000000..0d4b831812c
--- /dev/null
+++ b/core/Command/TaskProcessing/EnabledCommand.php
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Core\Command\TaskProcessing;
+
+use OC\Core\Command\Base;
+use OCP\IAppConfig;
+use OCP\TaskProcessing\IManager;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class EnabledCommand extends Base {
+ public function __construct(
+ protected IManager $taskProcessingManager,
+ private IAppConfig $appConfig,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this
+ ->setName('taskprocessing:task-type:set-enabled')
+ ->setDescription('Enable or disable a task type')
+ ->addArgument(
+ 'task-type-id',
+ InputArgument::REQUIRED,
+ 'ID of the task type to configure'
+ )
+ ->addArgument(
+ 'enabled',
+ InputArgument::REQUIRED,
+ 'status of the task type availability. Set 1 to enable and 0 to disable.'
+ );
+ parent::configure();
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $enabled = (bool)$input->getArgument('enabled');
+ $taskType = $input->getArgument('task-type-id');
+ $json = $this->appConfig->getValueString('core', 'ai.taskprocessing_type_preferences', lazy: true);
+ try {
+ if ($json === '') {
+ $taskTypeSettings = [];
+ } else {
+ $taskTypeSettings = json_decode($json, true, flags: JSON_THROW_ON_ERROR);
+ }
+
+ $taskTypeSettings[$taskType] = $enabled;
+
+ $this->appConfig->setValueString('core', 'ai.taskprocessing_type_preferences', json_encode($taskTypeSettings), lazy: true);
+ $this->writeArrayInOutputFormat($input, $output, $taskTypeSettings);
+ return 0;
+ } catch (\JsonException $e) {
+ throw new \JsonException('Error in TaskType DB entry');
+ }
+
+ }
+}
diff --git a/core/Command/TaskProcessing/GetCommand.php b/core/Command/TaskProcessing/GetCommand.php
new file mode 100644
index 00000000000..5c4fd17f2f8
--- /dev/null
+++ b/core/Command/TaskProcessing/GetCommand.php
@@ -0,0 +1,42 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Core\Command\TaskProcessing;
+
+use OC\Core\Command\Base;
+use OCP\TaskProcessing\IManager;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class GetCommand extends Base {
+ public function __construct(
+ protected IManager $taskProcessingManager,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this
+ ->setName('taskprocessing:task:get')
+ ->setDescription('Display all information for a specific task')
+ ->addArgument(
+ 'task-id',
+ InputArgument::REQUIRED,
+ 'ID of the task to display'
+ );
+ parent::configure();
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $taskId = (int)$input->getArgument('task-id');
+ $task = $this->taskProcessingManager->getTask($taskId);
+ $jsonTask = $task->jsonSerialize();
+ $jsonTask['error_message'] = $task->getErrorMessage();
+ $this->writeArrayInOutputFormat($input, $output, $jsonTask);
+ return 0;
+ }
+}
diff --git a/core/Command/TaskProcessing/ListCommand.php b/core/Command/TaskProcessing/ListCommand.php
new file mode 100644
index 00000000000..81eb258d35d
--- /dev/null
+++ b/core/Command/TaskProcessing/ListCommand.php
@@ -0,0 +1,96 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Core\Command\TaskProcessing;
+
+use OC\Core\Command\Base;
+use OCP\TaskProcessing\IManager;
+use OCP\TaskProcessing\Task;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class ListCommand extends Base {
+ public function __construct(
+ protected IManager $taskProcessingManager,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this
+ ->setName('taskprocessing:task:list')
+ ->setDescription('list tasks')
+ ->addOption(
+ 'userIdFilter',
+ 'u',
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks for one user ID'
+ )
+ ->addOption(
+ 'type',
+ 't',
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks for one task type'
+ )
+ ->addOption(
+ 'appId',
+ null,
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks for one app ID'
+ )
+ ->addOption(
+ 'customId',
+ null,
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks for one custom ID'
+ )
+ ->addOption(
+ 'status',
+ 's',
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks that have a specific status (STATUS_UNKNOWN=0, STATUS_SCHEDULED=1, STATUS_RUNNING=2, STATUS_SUCCESSFUL=3, STATUS_FAILED=4, STATUS_CANCELLED=5)'
+ )
+ ->addOption(
+ 'scheduledAfter',
+ null,
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks that were scheduled after a specific date (Unix timestamp)'
+ )
+ ->addOption(
+ 'endedBefore',
+ null,
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks that ended before a specific date (Unix timestamp)'
+ );
+ parent::configure();
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $userIdFilter = $input->getOption('userIdFilter');
+ if ($userIdFilter === null) {
+ $userIdFilter = '';
+ } elseif ($userIdFilter === '') {
+ $userIdFilter = null;
+ }
+ $type = $input->getOption('type');
+ $appId = $input->getOption('appId');
+ $customId = $input->getOption('customId');
+ $status = $input->getOption('status');
+ $scheduledAfter = $input->getOption('scheduledAfter');
+ $endedBefore = $input->getOption('endedBefore');
+
+ $tasks = $this->taskProcessingManager->getTasks($userIdFilter, $type, $appId, $customId, $status, $scheduledAfter, $endedBefore);
+ $arrayTasks = array_map(static function (Task $task) {
+ $jsonTask = $task->jsonSerialize();
+ $jsonTask['error_message'] = $task->getErrorMessage();
+ return $jsonTask;
+ }, $tasks);
+
+ $this->writeArrayInOutputFormat($input, $output, $arrayTasks);
+ return 0;
+ }
+}
diff --git a/core/Command/TaskProcessing/Statistics.php b/core/Command/TaskProcessing/Statistics.php
new file mode 100644
index 00000000000..86478b34db1
--- /dev/null
+++ b/core/Command/TaskProcessing/Statistics.php
@@ -0,0 +1,194 @@
+<?php
+
+/**
+ * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Core\Command\TaskProcessing;
+
+use OC\Core\Command\Base;
+use OCP\TaskProcessing\IManager;
+use OCP\TaskProcessing\Task;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class Statistics extends Base {
+ public function __construct(
+ protected IManager $taskProcessingManager,
+ ) {
+ parent::__construct();
+ }
+
+ protected function configure() {
+ $this
+ ->setName('taskprocessing:task:stats')
+ ->setDescription('get statistics for tasks')
+ ->addOption(
+ 'userIdFilter',
+ 'u',
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks for one user ID'
+ )
+ ->addOption(
+ 'type',
+ 't',
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks for one task type'
+ )
+ ->addOption(
+ 'appId',
+ null,
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks for one app ID'
+ )
+ ->addOption(
+ 'customId',
+ null,
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks for one custom ID'
+ )
+ ->addOption(
+ 'status',
+ 's',
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks that have a specific status (STATUS_UNKNOWN=0, STATUS_SCHEDULED=1, STATUS_RUNNING=2, STATUS_SUCCESSFUL=3, STATUS_FAILED=4, STATUS_CANCELLED=5)'
+ )
+ ->addOption(
+ 'scheduledAfter',
+ null,
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks that were scheduled after a specific date (Unix timestamp)'
+ )
+ ->addOption(
+ 'endedBefore',
+ null,
+ InputOption::VALUE_OPTIONAL,
+ 'only get the tasks that ended before a specific date (Unix timestamp)'
+ );
+ parent::configure();
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output): int {
+ $userIdFilter = $input->getOption('userIdFilter');
+ if ($userIdFilter === null) {
+ $userIdFilter = '';
+ } elseif ($userIdFilter === '') {
+ $userIdFilter = null;
+ }
+ $type = $input->getOption('type');
+ $appId = $input->getOption('appId');
+ $customId = $input->getOption('customId');
+ $status = $input->getOption('status');
+ $scheduledAfter = $input->getOption('scheduledAfter');
+ $endedBefore = $input->getOption('endedBefore');
+
+ $tasks = $this->taskProcessingManager->getTasks($userIdFilter, $type, $appId, $customId, $status, $scheduledAfter, $endedBefore);
+
+ $stats = ['Number of tasks' => count($tasks)];
+
+ $maxRunningTime = 0;
+ $totalRunningTime = 0;
+ $runningTimeCount = 0;
+
+ $maxQueuingTime = 0;
+ $totalQueuingTime = 0;
+ $queuingTimeCount = 0;
+
+ $maxUserWaitingTime = 0;
+ $totalUserWaitingTime = 0;
+ $userWaitingTimeCount = 0;
+
+ $maxInputSize = 0;
+ $maxOutputSize = 0;
+ $inputCount = 0;
+ $inputSum = 0;
+ $outputCount = 0;
+ $outputSum = 0;
+
+ foreach ($tasks as $task) {
+ // running time
+ if ($task->getStartedAt() !== null && $task->getEndedAt() !== null) {
+ $taskRunningTime = $task->getEndedAt() - $task->getStartedAt();
+ $totalRunningTime += $taskRunningTime;
+ $runningTimeCount++;
+ if ($taskRunningTime >= $maxRunningTime) {
+ $maxRunningTime = $taskRunningTime;
+ }
+ }
+ // queuing time
+ if ($task->getScheduledAt() !== null && $task->getStartedAt() !== null) {
+ $taskQueuingTime = $task->getStartedAt() - $task->getScheduledAt();
+ $totalQueuingTime += $taskQueuingTime;
+ $queuingTimeCount++;
+ if ($taskQueuingTime >= $maxQueuingTime) {
+ $maxQueuingTime = $taskQueuingTime;
+ }
+ }
+ // user waiting time
+ if ($task->getScheduledAt() !== null && $task->getEndedAt() !== null) {
+ $taskUserWaitingTime = $task->getEndedAt() - $task->getScheduledAt();
+ $totalUserWaitingTime += $taskUserWaitingTime;
+ $userWaitingTimeCount++;
+ if ($taskUserWaitingTime >= $maxUserWaitingTime) {
+ $maxUserWaitingTime = $taskUserWaitingTime;
+ }
+ }
+ // input/output sizes
+ if ($task->getStatus() === Task::STATUS_SUCCESSFUL) {
+ $outputString = json_encode($task->getOutput());
+ if ($outputString !== false) {
+ $outputCount++;
+ $outputLength = strlen($outputString);
+ $outputSum += $outputLength;
+ if ($outputLength > $maxOutputSize) {
+ $maxOutputSize = $outputLength;
+ }
+ }
+ }
+ $inputString = json_encode($task->getInput());
+ if ($inputString !== false) {
+ $inputCount++;
+ $inputLength = strlen($inputString);
+ $inputSum += $inputLength;
+ if ($inputLength > $maxInputSize) {
+ $maxInputSize = $inputLength;
+ }
+ }
+ }
+
+ if ($runningTimeCount > 0) {
+ $stats['Max running time'] = $maxRunningTime;
+ $averageRunningTime = $totalRunningTime / $runningTimeCount;
+ $stats['Average running time'] = (int)$averageRunningTime;
+ $stats['Running time count'] = $runningTimeCount;
+ }
+ if ($queuingTimeCount > 0) {
+ $stats['Max queuing time'] = $maxQueuingTime;
+ $averageQueuingTime = $totalQueuingTime / $queuingTimeCount;
+ $stats['Average queuing time'] = (int)$averageQueuingTime;
+ $stats['Queuing time count'] = $queuingTimeCount;
+ }
+ if ($userWaitingTimeCount > 0) {
+ $stats['Max user waiting time'] = $maxUserWaitingTime;
+ $averageUserWaitingTime = $totalUserWaitingTime / $userWaitingTimeCount;
+ $stats['Average user waiting time'] = (int)$averageUserWaitingTime;
+ $stats['User waiting time count'] = $userWaitingTimeCount;
+ }
+ if ($outputCount > 0) {
+ $stats['Max output size (bytes)'] = $maxOutputSize;
+ $averageOutputSize = $outputSum / $outputCount;
+ $stats['Average output size (bytes)'] = (int)$averageOutputSize;
+ $stats['Number of tasks with output'] = $outputCount;
+ }
+ if ($inputCount > 0) {
+ $stats['Max input size (bytes)'] = $maxInputSize;
+ $averageInputSize = $inputSum / $inputCount;
+ $stats['Average input size (bytes)'] = (int)$averageInputSize;
+ $stats['Number of tasks with input'] = $inputCount;
+ }
+
+ $this->writeArrayInOutputFormat($input, $output, $stats);
+ return 0;
+ }
+}