ソースを参照

fix: address review comments

Signed-off-by: Marcel Klehr <mklehr@gmx.net>
pull/45094/head
Marcel Klehr 1ヶ月前
コミット
ec27c538b5

+ 7
- 5
core/Controller/TaskProcessingApiController.php ファイルの表示

@@ -98,7 +98,7 @@ class TaskProcessingApiController extends \OCP\AppFramework\OCSController {
/**
* This endpoint allows scheduling a task
*
* @param array<string, mixed> $input Input text
* @param array<string, mixed> $input Task's input parameters
* @param string $type Type of the task
* @param string $appId ID of the app that will execute the task
* @param string $identifier An arbitrary identifier for the task
@@ -171,7 +171,7 @@ class TaskProcessingApiController extends \OCP\AppFramework\OCSController {
*
* @param int $id The id of the task
*
* @return DataResponse<Http::STATUS_OK, array{}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
* @return DataResponse<Http::STATUS_OK, null, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
*
* 200: Task returned
*/
@@ -260,10 +260,10 @@ class TaskProcessingApiController extends \OCP\AppFramework\OCSController {

/**
* @param Task $task
* @return list<mixed>
* @return list<int>
* @throws \OCP\TaskProcessing\Exception\NotFoundException
*/
private function extractFileIdsFromTask(Task $task) {
private function extractFileIdsFromTask(Task $task): array {
$ids = [];
$taskTypes = $this->taskProcessingManager->getAvailableTaskTypes();
if (!isset($taskTypes[$task->getTaskTypeId()])) {
@@ -272,6 +272,7 @@ class TaskProcessingApiController extends \OCP\AppFramework\OCSController {
$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 += $inputSlot;
@@ -283,6 +284,7 @@ class TaskProcessingApiController extends \OCP\AppFramework\OCSController {
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 += $outputSlot;
@@ -292,7 +294,7 @@ class TaskProcessingApiController extends \OCP\AppFramework\OCSController {
}
}
}
return $ids;
return array_values($ids);
}

/**

+ 3
- 3
core/ResponseDefinitions.php ファイルの表示

@@ -195,11 +195,11 @@ namespace OCA\Core;
* @psalm-type CoreTaskProcessingTask = array{
* id: int,
* type: string,
* status: 0|1|2|3|4|5,
* status: 'STATUS_CANCELLED'|'STATUS_FAILED'|'STATUS_SUCCESSFUL'|'STATUS_RUNNING'|'STATUS_SCHEDULED'|'STATUS_UNKNOWN',
* userId: ?string,
* appId: string,
* input: ?array<string, mixed>,
* output: ?array<string, mixed>,
* input: array<string, numeric|list<numeric>|string|list<string>>,
* output: ?array<string, numeric|list<numeric>|string|list<string>>,
* identifier: ?string,
* completionExpectedAt: ?int,
* progress: ?float

+ 49
- 13
core/openapi.json ファイルの表示

@@ -509,15 +509,14 @@
"type": "string"
},
"status": {
"type": "integer",
"format": "int64",
"type": "string",
"enum": [
0,
1,
2,
3,
4,
5
"STATUS_CANCELLED",
"STATUS_FAILED",
"STATUS_SUCCESSFUL",
"STATUS_RUNNING",
"STATUS_SCHEDULED",
"STATUS_UNKNOWN"
]
},
"userId": {
@@ -529,16 +528,53 @@
},
"input": {
"type": "object",
"nullable": true,
"additionalProperties": {
"type": "object"
"anyOf": [
{
"type": "number"
},
{
"type": "array",
"items": {
"type": "number"
}
},
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
}
},
"output": {
"type": "object",
"nullable": true,
"additionalProperties": {
"type": "object"
"anyOf": [
{
"type": "number"
},
{
"type": "array",
"items": {
"type": "number"
}
},
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
}
},
"identifier": {
@@ -3410,7 +3446,7 @@
{
"name": "input",
"in": "query",
"description": "Input text",
"description": "Task's input parameters",
"required": true,
"schema": {
"type": "string"
@@ -3861,7 +3897,7 @@
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object"
"nullable": true
}
}
}

+ 2
- 2
lib/private/AppFramework/Bootstrap/RegistrationContext.php ファイルの表示

@@ -164,10 +164,10 @@ class RegistrationContext {
private array $teamResourceProviders = [];

/** @var ServiceRegistration<\OCP\TaskProcessing\IProvider>[] */
private $taskProcessingProviders = [];
private array $taskProcessingProviders = [];

/** @var ServiceRegistration<\OCP\TaskProcessing\ITaskType>[] */
private $taskProcessingTaskTypes = [];
private array $taskProcessingTaskTypes = [];

public function __construct(LoggerInterface $logger) {
$this->logger = $logger;

+ 39
- 30
lib/private/TaskProcessing/Manager.php ファイルの表示

@@ -505,9 +505,10 @@ class Manager implements IManager {
}

/**
* @param array<string,mixed> $array The array to filter
* @param array<string, mixed> ...$specs the specs that define which keys to keep
* @return array<string, mixed>
* @param array<array-key, T> $array The array to filter
* @param ShapeDescriptor[] ...$specs the specs that define which keys to keep
* @return array<array-key, T>
* @psalm-template T
*/
private function removeSuperfluousArrayKeys(array $array, ...$specs): array {
$keys = array_unique(array_reduce($specs, fn ($carry, $spec) => $carry + array_keys($spec), []));
@@ -679,7 +680,7 @@ class Manager implements IManager {
$this->validateOutput($outputShape, $result);
$this->validateOutput($optionalOutputShape, $result, true);
$output = $this->removeSuperfluousArrayKeys($result, $outputShape, $optionalOutputShape);
// extract base64 data and put it in files, replace it with file ids
// extract raw data and put it in files, replace it with file ids
$output = $this->encapsulateOutputFileData($output, $outputShape, $optionalOutputShape);
$task->setOutput($output);
$task->setProgress(1);
@@ -726,36 +727,12 @@ class Manager implements IManager {
}
}

public function getUserTask(int $id, ?string $userId): Task {
try {
$taskEntity = $this->taskMapper->findByIdAndUser($id, $userId);
return $taskEntity->toPublicTask();
} catch (DoesNotExistException $e) {
throw new \OCP\TaskProcessing\Exception\NotFoundException('Could not find the task', 0, $e);
} catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) {
throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding the task', 0, $e);
} catch (\JsonException $e) {
throw new \OCP\TaskProcessing\Exception\Exception('There was a problem parsing JSON after finding the task', 0, $e);
}
}

public function getUserTasksByApp(?string $userId, string $appId, ?string $identifier = null): array {
try {
$taskEntities = $this->taskMapper->findUserTasksByApp($userId, $appId, $identifier);
return array_map(fn ($taskEntity): Task => $taskEntity->toPublicTask(), $taskEntities);
} catch (\OCP\DB\Exception $e) {
throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding a task', 0, $e);
} catch (\JsonException $e) {
throw new \OCP\TaskProcessing\Exception\Exception('There was a problem parsing JSON after finding a task', 0, $e);
}
}

/**
* Takes task input or output data and replaces fileIds with base64 data
*
* @param array<array-key, list<numeric|string>|numeric|string> $input
* @param ShapeDescriptor[] ...$specs the specs
* @param array $input
* @return array
* @return array<array-key, list<File|numeric|string>|numeric|string|File>
* @throws GenericFileException
* @throws LockedException
* @throws NotPermittedException
@@ -805,6 +782,30 @@ class Manager implements IManager {
return $newInputOutput;
}

public function getUserTask(int $id, ?string $userId): Task {
try {
$taskEntity = $this->taskMapper->findByIdAndUser($id, $userId);
return $taskEntity->toPublicTask();
} catch (DoesNotExistException $e) {
throw new \OCP\TaskProcessing\Exception\NotFoundException('Could not find the task', 0, $e);
} catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) {
throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding the task', 0, $e);
} catch (\JsonException $e) {
throw new \OCP\TaskProcessing\Exception\Exception('There was a problem parsing JSON after finding the task', 0, $e);
}
}

public function getUserTasksByApp(?string $userId, string $appId, ?string $identifier = null): array {
try {
$taskEntities = $this->taskMapper->findUserTasksByApp($userId, $appId, $identifier);
return array_map(fn ($taskEntity): Task => $taskEntity->toPublicTask(), $taskEntities);
} catch (\OCP\DB\Exception $e) {
throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding a task', 0, $e);
} catch (\JsonException $e) {
throw new \OCP\TaskProcessing\Exception\Exception('There was a problem parsing JSON after finding a task', 0, $e);
}
}

/**
*Takes task input or output and replaces base64 data with file ids
*
@@ -846,6 +847,14 @@ class Manager implements IManager {
return $newOutput;
}

/**
* @param Task $task
* @return array<array-key, list<numeric|string|File>|numeric|string|File>
* @throws GenericFileException
* @throws LockedException
* @throws NotPermittedException
* @throws ValidationException
*/
public function prepareInputData(Task $task): array {
$taskTypes = $this->getAvailableTaskTypes();
$inputShape = $taskTypes[$task->getTaskTypeId()]['inputShape'];

+ 2
- 1
lib/public/TaskProcessing/IManager.php ファイルの表示

@@ -26,6 +26,7 @@ declare(strict_types=1);

namespace OCP\TaskProcessing;

use OCP\Files\File;
use OCP\Files\GenericFileException;
use OCP\Files\NotPermittedException;
use OCP\Lock\LockedException;
@@ -150,7 +151,7 @@ interface IManager {
* ie. this replaces file ids with base64 data
*
* @param Task $task
* @return array<string, mixed>
* @return array<array-key, list<numeric|string|File>|numeric|string|File>
* @throws NotPermittedException
* @throws GenericFileException
* @throws LockedException

+ 4
- 3
lib/public/TaskProcessing/ISynchronousProvider.php ファイルの表示

@@ -26,6 +26,7 @@ declare(strict_types=1);

namespace OCP\TaskProcessing;

use OCP\Files\File;
use OCP\TaskProcessing\Exception\ProcessingException;

/**
@@ -38,11 +39,11 @@ interface ISynchronousProvider extends IProvider {
/**
* Returns the shape of optional output parameters
*
* @since 30.0.0
* @param null|string $userId The user that created the current task
* @param array<string, mixed> $input The task input
* @psalm-return array<string, mixed>
* @param array<string, list<numeric|string|File>|numeric|string|File> $input The task input
* @psalm-return array<string, list<numeric|string>|numeric|string>
* @throws ProcessingException
*@since 30.0.0
*/
public function process(?string $userId, array $input): array;
}

+ 30
- 12
lib/public/TaskProcessing/Task.php ファイルの表示

@@ -75,7 +75,8 @@ final class Task implements \JsonSerializable {
protected int $status = self::STATUS_UNKNOWN;

/**
* @param array<string,mixed> $input
* @param string $taskTypeId
* @param array<string,list<numeric|string>|numeric|string> $input
* @param string $appId
* @param string|null $userId
* @param null|string $identifier An arbitrary identifier for this task. max length: 255 chars
@@ -146,6 +147,7 @@ final class Task implements \JsonSerializable {
}

/**
* @param null|array<array-key, list<numeric|string>|numeric|string> $output
* @since 30.0.0
*/
final public function setOutput(?array $output): void {
@@ -153,7 +155,7 @@ final class Task implements \JsonSerializable {
}

/**
* @return array<array-key, mixed>|null
* @return array<array-key, list<numeric|string>|numeric|string>|null
* @since 30.0.0
*/
final public function getOutput(): ?array {
@@ -161,7 +163,7 @@ final class Task implements \JsonSerializable {
}

/**
* @return array<array-key, mixed>
* @return array<array-key, list<numeric|string>|numeric|string>
* @since 30.0.0
*/
final public function getInput(): array {
@@ -193,20 +195,20 @@ final class Task implements \JsonSerializable {
}

/**
* @psalm-return array{id: ?int, type: string, status: self::STATUS_*, userId: ?string, appId: string, input: ?array<array-key, mixed>, output: ?array<array-key, mixed>, identifier: ?string, completionExpectedAt: ?int, progress: ?float}
* @psalm-return array{id: ?int, type: string, status: 'STATUS_CANCELLED'|'STATUS_FAILED'|'STATUS_SUCCESSFUL'|'STATUS_RUNNING'|'STATUS_SCHEDULED'|'STATUS_UNKNOWN', userId: ?string, appId: string, input: array<array-key, list<numeric|string>|numeric|string>, output: ?array<array-key, list<numeric|string>|numeric|string>, identifier: ?string, completionExpectedAt: ?int, progress: ?float}
* @since 30.0.0
*/
public function jsonSerialize(): array {
final public function jsonSerialize(): array {
return [
'id' => $this->getId(),
'type' => $this->getTaskTypeId(),
'status' => $this->getStatus(),
'status' => self::statusToString($this->getStatus()),
'userId' => $this->getUserId(),
'appId' => $this->getAppId(),
'input' => $this->getInput(),
'output' => $this->getOutput(),
'identifier' => $this->getIdentifier(),
'completionExpectedAt' => $this->getCompletionExpectedAt()->getTimestamp(),
'completionExpectedAt' => $this->getCompletionExpectedAt()?->getTimestamp(),
'progress' => $this->getProgress(),
];
}
@@ -216,7 +218,7 @@ final class Task implements \JsonSerializable {
* @return void
* @since 30.0.0
*/
public function setErrorMessage(?string $error) {
final public function setErrorMessage(?string $error) {
$this->errorMessage = $error;
}

@@ -224,7 +226,7 @@ final class Task implements \JsonSerializable {
* @return string|null
* @since 30.0.0
*/
public function getErrorMessage(): ?string {
final public function getErrorMessage(): ?string {
return $this->errorMessage;
}

@@ -233,7 +235,7 @@ final class Task implements \JsonSerializable {
* @return void
* @since 30.0.0
*/
public function setInput(array $input): void {
final public function setInput(array $input): void {
$this->input = $input;
}

@@ -243,7 +245,7 @@ final class Task implements \JsonSerializable {
* @throws ValidationException
* @since 30.0.0
*/
public function setProgress(?float $progress): void {
final public function setProgress(?float $progress): void {
if ($progress < 0 || $progress > 1.0) {
throw new ValidationException('Progress must be between 0.0 and 1.0 inclusively; ' . $progress . ' given');
}
@@ -254,7 +256,23 @@ final class Task implements \JsonSerializable {
* @return float|null
* @since 30.0.0
*/
public function getProgress(): ?float {
final public function getProgress(): ?float {
return $this->progress;
}

/**
* @param int $status
* @return 'STATUS_CANCELLED'|'STATUS_FAILED'|'STATUS_SUCCESSFUL'|'STATUS_RUNNING'|'STATUS_SCHEDULED'|'STATUS_UNKNOWN'
* @since 30.0.0
*/
final public static function statusToString(int $status): string {
return match ($status) {
self::STATUS_CANCELLED => 'STATUS_CANCELLED',
self::STATUS_FAILED => 'STATUS_FAILED',
self::STATUS_SUCCESSFUL => 'STATUS_SUCCESSFUL',
self::STATUS_RUNNING => 'STATUS_RUNNING',
self::STATUS_SCHEDULED => 'STATUS_SCHEDULED',
default => 'STATUS_UNKNOWN',
};
}
}

読み込み中…
キャンセル
保存