aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/TaskProcessing/Manager.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/TaskProcessing/Manager.php')
-rw-r--r--lib/private/TaskProcessing/Manager.php94
1 files changed, 94 insertions, 0 deletions
diff --git a/lib/private/TaskProcessing/Manager.php b/lib/private/TaskProcessing/Manager.php
index 11fb2bed559..e288f2981a8 100644
--- a/lib/private/TaskProcessing/Manager.php
+++ b/lib/private/TaskProcessing/Manager.php
@@ -30,6 +30,7 @@ use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\Files\SimpleFS\ISimpleFolder;
use OCP\Http\Client\IClientService;
use OCP\IAppConfig;
use OCP\ICache;
@@ -78,6 +79,8 @@ class Manager implements IManager {
'ai.taskprocessing_provider_preferences',
];
+ public const MAX_TASK_AGE_SECONDS = 60 * 60 * 24 * 30 * 4; // 4 months
+
/** @var list<IProvider>|null */
private ?array $providers = null;
@@ -1449,6 +1452,97 @@ class Manager implements IManager {
}
/**
+ * @param Task $task
+ * @return list<int>
+ * @throws NotFoundException
+ */
+ public function extractFileIdsFromTask(Task $task): array {
+ $ids = [];
+ $taskTypes = $this->getAvailableTaskTypes();
+ if (!isset($taskTypes[$task->getTaskTypeId()])) {
+ throw new NotFoundException('Could not find task type');
+ }
+ $taskType = $taskTypes[$task->getTaskTypeId()];
+ foreach ($taskType['inputShape'] + $taskType['optionalInputShape'] as $key => $descriptor) {
+ if (in_array(EShapeType::getScalarType($descriptor->getShapeType()), [EShapeType::File, EShapeType::Image, EShapeType::Audio, EShapeType::Video], true)) {
+ /** @var int|list<int> $inputSlot */
+ $inputSlot = $task->getInput()[$key];
+ if (is_array($inputSlot)) {
+ $ids = array_merge($inputSlot, $ids);
+ } else {
+ $ids[] = $inputSlot;
+ }
+ }
+ }
+ if ($task->getOutput() !== null) {
+ foreach ($taskType['outputShape'] + $taskType['optionalOutputShape'] as $key => $descriptor) {
+ if (in_array(EShapeType::getScalarType($descriptor->getShapeType()), [EShapeType::File, EShapeType::Image, EShapeType::Audio, EShapeType::Video], true)) {
+ /** @var int|list<int> $outputSlot */
+ $outputSlot = $task->getOutput()[$key];
+ if (is_array($outputSlot)) {
+ $ids = array_merge($outputSlot, $ids);
+ } else {
+ $ids[] = $outputSlot;
+ }
+ }
+ }
+ }
+ return $ids;
+ }
+
+ /**
+ * @param ISimpleFolder $folder
+ * @param int $ageInSeconds
+ * @return \Generator
+ */
+ public function clearFilesOlderThan(ISimpleFolder $folder, int $ageInSeconds = self::MAX_TASK_AGE_SECONDS): \Generator {
+ foreach ($folder->getDirectoryListing() as $file) {
+ if ($file->getMTime() < time() - $ageInSeconds) {
+ try {
+ $fileName = $file->getName();
+ $file->delete();
+ yield $fileName;
+ } catch (NotPermittedException $e) {
+ $this->logger->warning('Failed to delete a stale task processing file', ['exception' => $e]);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param int $ageInSeconds
+ * @return \Generator
+ * @throws Exception
+ * @throws InvalidPathException
+ * @throws NotFoundException
+ * @throws \JsonException
+ * @throws \OCP\Files\NotFoundException
+ */
+ public function cleanupTaskProcessingTaskFiles(int $ageInSeconds = self::MAX_TASK_AGE_SECONDS): \Generator {
+ $taskIdsToCleanup = [];
+ foreach ($this->taskMapper->getTasksToCleanup($ageInSeconds) as $task) {
+ $taskIdsToCleanup[] = $task->getId();
+ $ocpTask = $task->toPublicTask();
+ $fileIds = $this->extractFileIdsFromTask($ocpTask);
+ foreach ($fileIds as $fileId) {
+ // only look for output files stored in appData/TaskProcessing/
+ $file = $this->rootFolder->getFirstNodeByIdInPath($fileId, '/' . $this->rootFolder->getAppDataDirectoryName() . '/core/TaskProcessing/');
+ if ($file instanceof File) {
+ try {
+ $fileId = $file->getId();
+ $fileName = $file->getName();
+ $file->delete();
+ yield ['task_id' => $task->getId(), 'file_id' => $fileId, 'file_name' => $fileName];
+ } catch (NotPermittedException $e) {
+ $this->logger->warning('Failed to delete a stale task processing file', ['exception' => $e]);
+ }
+ }
+ }
+ }
+ return $taskIdsToCleanup;
+ }
+
+ /**
* Make a request to the task's webhookUri if necessary
*
* @param Task $task