diff --git a/app/config/collections.php b/app/config/collections.php index 7678b9c69..56883fc29 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -1915,7 +1915,18 @@ $collections = [ 'filters' => [], ], [ - '$id' => 'functionId', + '$id' => 'resourceId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'resourceType', 'type' => Database::VAR_STRING, 'format' => '', 'size' => Database::LENGTH_KEY, @@ -1981,39 +1992,6 @@ $collections = [ 'array' => false, 'filters' => [], ], - [ - '$id' => 'status', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 128, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'buildStdout', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 4096, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'buildStderr', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 4096, - 'signed' => true, - 'required' => false, - 'default' => '', - 'array' => false, - 'filters' => [], - ], [ '$id' => 'deploy', 'type' => Database::VAR_BOOLEAN, @@ -2028,9 +2006,9 @@ $collections = [ ], 'indexes' => [ [ - '$id' => '_key_function', + '$id' => '_key_resource', 'type' => Database::INDEX_KEY, - 'attributes' => ['functionId'], + 'attributes' => ['resourceId'], 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], ], @@ -2050,7 +2028,7 @@ $collections = [ 'name' => 'Builds', 'attributes' => [ [ - '$id' => 'dateCreated', + '$id' => 'startTime', 'type' => Database::VAR_INTEGER, 'format' => '', 'size' => 0, @@ -2060,6 +2038,17 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => 'deploymentId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], [ '$id' => 'runtime', 'type' => Database::VAR_STRING, @@ -2116,7 +2105,7 @@ $collections = [ 'filters' => [], ], [ - '$id' => 'time', + '$id' => 'endTime', 'type' => Database::VAR_INTEGER, 'format' => '', 'size' => 0, @@ -2127,15 +2116,15 @@ $collections = [ 'filters' => [], ], [ - '$id' => 'vars', - 'type' => Database::VAR_STRING, + '$id' => 'duration', + 'type' => Database::VAR_INTEGER, 'format' => '', - 'size' => 16384, + 'size' => 0, 'signed' => true, 'required' => false, - 'default' => new stdClass(), + 'default' => null, 'array' => false, - 'filters' => ['json'], + 'filters' => [], ], [ '$id' => 'sourceType', diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index cb086ae92..fe2273d12 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -556,7 +556,8 @@ App::post('/v1/functions/:functionId/deployments') // Remove deploy for all other deployments. $deployments = $dbForProject->find('deployments', [ new Query('deploy', Query::TYPE_EQUAL, [true]), - new Query('functionId', Query::TYPE_EQUAL, [$functionId]) + new Query('resourceId', Query::TYPE_EQUAL, [$functionId]), + new Query('resourceType', Query::TYPE_EQUAL, ['functions']) ]); foreach ($deployments as $deployment) { @@ -570,15 +571,13 @@ App::post('/v1/functions/:functionId/deployments') '$id' => $deploymentId, '$read' => ['role:all'], '$write' => ['role:all'], - 'functionId' => $function->getId(), + 'resourceId' => $function->getId(), + 'resourceType' => 'functions', 'dateCreated' => time(), 'entrypoint' => $entrypoint, 'path' => $path, 'size' => $size, 'search' => implode(' ', [$deploymentId, $entrypoint]), - 'status' => 'processing', - 'buildStdout' => '', - 'buildStderr' => '', 'deploy' => ($deploy === 'true'), ])); @@ -670,22 +669,12 @@ App::get('/v1/functions/:functionId/deployments') $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); } - $queries[] = new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]); + $queries[] = new Query('resourceId', Query::TYPE_EQUAL, [$function->getId()]); + $queries[] = new Query('resourceType', Query::TYPE_EQUAL, ['functions']); $results = $dbForProject->find('deployments', $queries, $limit, $offset, [], [$orderType], $cursorDeployment ?? null, $cursorDirection); $sum = $dbForProject->count('deployments', $queries, APP_LIMIT_COUNT); - // Get Current Build Data - foreach ($results as &$deployment) { - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); - - $deployment['status'] = $build->getAttribute('status', 'processing'); - $deployment['buildStdout'] = $build->getAttribute('stdout', ''); - $deployment['buildStderr'] = $build->getAttribute('stderr', ''); - } - - var_dump($results); - $response->dynamic(new Document([ 'deployments' => $results, 'sum' => $sum, @@ -719,7 +708,7 @@ App::get('/v1/functions/:functionId/deployments/:deploymentId') $deployment = $dbForProject->getDocument('deployments', $deploymentId); - if ($deployment->getAttribute('functionId') !== $function->getId()) { + if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new Exception('Deployment not found', 404); } @@ -761,7 +750,7 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId') $deployment = $dbForProject->getDocument('deployments', $deploymentId); - if ($deployment->getAttribute('functionId') !== $function->getId()) { + if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new Exception('Deployment not found', 404); } @@ -857,7 +846,7 @@ App::post('/v1/functions/:functionId/executions') $deployment = Authorization::skip(fn() => $dbForProject->getDocument('deployments', $function->getAttribute('deployment'))); - if ($deployment->getAttribute('functionId') !== $function->getId()) { + if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new Exception('Deployment not found. Deploy deployment before trying to execute a function', 404); } diff --git a/app/executor.php b/app/executor.php index 98ff3d9e0..104db6657 100644 --- a/app/executor.php +++ b/app/executor.php @@ -176,7 +176,7 @@ function createRuntimeServer(string $functionId, string $projectId, string $depl // Check if runtime is active $runtime = $runtimes[$function->getAttribute('runtime', '')] ?? null; - if ($deployment->getAttribute('functionId') !== $function->getId()) { + if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new Exception('deployment not found', 404); } @@ -186,6 +186,7 @@ function createRuntimeServer(string $functionId, string $projectId, string $depl // Process environment variables $vars = \array_merge($function->getAttribute('vars', []), [ + 'ENTRYPOINT_NAME' => $deployment->getAttribute('entrypoint', ''), 'APPWRITE_FUNCTION_ID' => $function->getId(), 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name', ''), 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), @@ -195,8 +196,6 @@ function createRuntimeServer(string $functionId, string $projectId, string $depl 'INTERNAL_RUNTIME_KEY' => $secret ]); - $vars = \array_merge($vars, $build->getAttribute('vars', [])); // for gettng endpoint. - $container = 'appwrite-function-' . $deployment->getId(); if ($activeFunctions->exists($container) && !(\substr($activeFunctions->get($container)['status'], 0, 2) === 'Up')) { // Remove container if not online @@ -328,7 +327,7 @@ function execute(string $trigger, string $projectId, string $executionId, string $deployment = $database->getDocument('deployments', $function->getAttribute('deployment', '')); $build = $database->getDocument('builds', $deployment->getAttribute('buildId', '')); - if ($deployment->getAttribute('functionId') !== $function->getId()) { + if ($deployment->getAttribute('resourceId') !== $function->getId()) { throw new Exception('Deployment not found', 404); } @@ -379,6 +378,7 @@ function execute(string $trigger, string $projectId, string $executionId, string // Process environment variables $vars = \array_merge($function->getAttribute('vars', []), [ + 'ENTRYPOINT_NAME' => $deployment->getAttribute('entrypoint', ''), 'APPWRITE_FUNCTION_ID' => $function->getId(), 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name', ''), 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), @@ -393,8 +393,6 @@ function execute(string $trigger, string $projectId, string $executionId, string 'APPWRITE_FUNCTION_PROJECT_ID' => $projectId, ]); - $vars = \array_merge($vars, $build->getAttribute('vars', [])); - $container = 'appwrite-function-' . $deployment->getId(); try { @@ -405,7 +403,8 @@ function execute(string $trigger, string $projectId, string $executionId, string '$id' => $buildId, '$read' => ($userId !== '') ? ['user:' . $userId] : [], '$write' => ['role:all'], - 'dateCreated' => time(), + 'startTime' => time(), + 'deploymentId' => $deployment->getId(), 'status' => 'processing', 'outputPath' => '', 'runtime' => $function->getAttribute('runtime', ''), @@ -413,15 +412,9 @@ function execute(string $trigger, string $projectId, string $executionId, string 'sourceType' => Storage::DEVICE_LOCAL, 'stdout' => '', 'stderr' => '', - 'time' => 0, - 'vars' => [ - 'ENTRYPOINT_NAME' => $deployment->getAttribute('entrypoint'), - 'APPWRITE_FUNCTION_ID' => $function->getId(), - 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name', ''), - 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'], - 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'], - 'APPWRITE_FUNCTION_PROJECT_ID' => $projectId, - ] + 'endTime' => 0, + 'duration' => 0, + 'search' => implode(' ', [$deployment->getId(), $buildId]), ])); $deployment->setAttribute('buildId', $buildId); @@ -475,6 +468,7 @@ function execute(string $trigger, string $projectId, string $executionId, string // Process environment variables $vars = \array_merge($function->getAttribute('vars', []), [ + 'ENTRYPOINT_NAME' => $deployment->getAttribute('entrypoint', ''), 'APPWRITE_FUNCTION_ID' => $function->getId(), 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name', ''), 'APPWRITE_FUNCTION_DEPLOYMENT' => $deployment->getId(), @@ -489,8 +483,6 @@ function execute(string $trigger, string $projectId, string $executionId, string 'APPWRITE_FUNCTION_PROJECT_ID' => $projectId ]); - $vars = \array_merge($vars, $build->getAttribute('vars', [])); - $stdout = ''; $stderr = ''; @@ -511,7 +503,7 @@ function execute(string $trigger, string $projectId, string $executionId, string $body = \json_encode([ 'path' => '/usr/code', - 'file' => $build->getAttribute('vars', [])['ENTRYPOINT_NAME'], + 'file' => $vars['ENTRYPOINT_NAME'], 'env' => $vars, 'payload' => $data, 'timeout' => $function->getAttribute('timeout', (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)) @@ -827,7 +819,8 @@ App::post('/v1/deployment') '$id' => $buildId, '$read' => (!empty($userId)) ? ['user:' . $userId] : [], '$write' => ['role:all'], - 'dateCreated' => time(), + 'startTime' => time(), + 'deploymentId' => $deploymentId, 'status' => 'processing', 'runtime' => $function->getAttribute('runtime'), 'outputPath' => '', @@ -835,15 +828,9 @@ App::post('/v1/deployment') 'sourceType' => Storage::DEVICE_LOCAL, 'stdout' => '', 'stderr' => '', - 'time' => 0, - 'vars' => [ - 'ENTRYPOINT_NAME' => $deployment->getAttribute('entrypoint'), - 'APPWRITE_FUNCTION_ID' => $function->getId(), - 'APPWRITE_FUNCTION_NAME' => $function->getAttribute('name', ''), - 'APPWRITE_FUNCTION_RUNTIME_NAME' => $runtime['name'], - 'APPWRITE_FUNCTION_RUNTIME_VERSION' => $runtime['version'], - 'APPWRITE_FUNCTION_PROJECT_ID' => $projectID, - ] + 'endTime' => 0, + 'duration' => 0, + 'search' => implode(' ', [$deployment->getId(), $buildId]) ])); $deployment->setAttribute('buildId', $buildId); @@ -1037,11 +1024,28 @@ function runBuildStage(string $buildId, string $projectID): Document throw new Exception('Code is not readable: ' . $build->getAttribute('source', '')); } - $vars = $build->getAttribute('vars', []); + $deployment = $database->getDocument('deployments', $build->getAttribute('deploymentId', '')); + $resourceId = $deployment->getAttribute('resourceId', ''); + $resourceType = $deployment->getAttribute('resourceType', ''); + + if (empty($resourceId)) { + throw new Exception('Invalid resource ID on build ' . $build->getId()); + } + + if (empty($resourceType)) { + throw new Exception('Invalid resource type on build' . $build->getId()); + } + + $resource = $database->getDocument($resourceType, $resourceId); + + if ($resource->isEmpty()) { + throw new Exception('Resource not found on build ' . $build->getId()); + } + + $vars = $resource->getAttribute('vars', []); // Start tracking time - $buildStart = \microtime(true); - $time = \time(); + $buildStart = \time(); $orchestration ->setCpus(App::getEnv('_APP_FUNCTIONS_CPUS', 0)) @@ -1067,7 +1071,7 @@ function runBuildStage(string $buildId, string $projectID): Document workdir: '/usr/code', labels: [ 'appwrite-type' => 'function', - 'appwrite-created' => strval($time), + 'appwrite-created' => strval($buildStart), 'appwrite-runtime' => $build->getAttribute('runtime', ''), 'appwrite-project' => $projectID, 'appwrite-build' => $build->getId(), @@ -1181,19 +1185,24 @@ function runBuildStage(string $buildId, string $projectID): Document ->setAttribute('status', 'ready') ->setAttribute('stdout', \utf8_encode(\mb_substr($buildStdout, -4096))) ->setAttribute('stderr', \utf8_encode(\mb_substr($buildStderr, -4096))) - ->setAttribute('time', $time); + ->setAttribute('startTime', $buildStart) + ->setAttribute('endTime', \time()) + ->setAttribute('duration', \time() - $buildStart); // Update build with built code attribute $build = $database->updateDocument('builds', $buildId, $build); - $buildEnd = \microtime(true); + $buildEnd = \time(); Console::info('Build Stage Ran in ' . ($buildEnd - $buildStart) . ' seconds'); } catch (Exception $e) { $build ->setAttribute('status', 'failed') ->setAttribute('stdout', \utf8_encode(\mb_substr($buildStdout, -4096))) - ->setAttribute('stderr', \utf8_encode(\mb_substr($e->getMessage(), -4096))); + ->setAttribute('stderr', \utf8_encode(\mb_substr($e->getMessage(), -4096))) + ->setAttribute('startTime', $buildStart) + ->setAttribute('endTime', \microtime(true)) + ->setAttribute('duration', \microtime(true) - $buildStart); $build = $database->updateDocument('builds', $buildId, $build); diff --git a/src/Appwrite/Utopia/Response/Model/Build.php b/src/Appwrite/Utopia/Response/Model/Build.php index fbf55a4a2..218e82d5e 100644 --- a/src/Appwrite/Utopia/Response/Model/Build.php +++ b/src/Appwrite/Utopia/Response/Model/Build.php @@ -16,12 +16,18 @@ class Build extends Model 'default' => '', 'example' => '5e5ea5c16897e', ]) - ->addRule('dateCreated', [ + ->addRule('startTime', [ 'type' => self::TYPE_INTEGER, 'description' => 'The deployment creation date in Unix timestamp.', 'default' => 0, 'example' => 1592981250, ]) + ->addRule('deploymentId', [ + 'type' => self::TYPE_STRING, + 'description' => 'The deployment that created this build', + 'default' => '', + 'example' => '5e5ea5c16897e', + ]) // Build Status // Failed - The deployment build has failed. More details can usually be found in buildStderr // Ready - The deployment build was successful and the deployment is ready to be deployed @@ -45,7 +51,13 @@ class Build extends Model 'default' => '', 'example' => '', ]) - ->addRule('time', [ + ->addRule('endTime', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'The time the build was finished in Unix timestamp.', + 'default' => 0, + 'example' => 0, + ]) + ->addRule('duration', [ 'type' => self::TYPE_INTEGER, 'description' => 'The build time in seconds.', 'default' => 0, diff --git a/src/Appwrite/Utopia/Response/Model/Deployment.php b/src/Appwrite/Utopia/Response/Model/Deployment.php index db1f518c9..b3ecf0290 100644 --- a/src/Appwrite/Utopia/Response/Model/Deployment.php +++ b/src/Appwrite/Utopia/Response/Model/Deployment.php @@ -16,12 +16,18 @@ class Deployment extends Model 'default' => '', 'example' => '5e5ea5c16897e', ]) - ->addRule('functionId', [ + ->addRule('resourceId', [ 'type' => self::TYPE_STRING, - 'description' => 'Function ID.', + 'description' => 'Resource ID.', 'default' => '', 'example' => '5e5ea6g16897e', ]) + ->addRule('resourceType', [ + 'type' => self::TYPE_STRING, + 'description' => 'Resource type.', + 'default' => '', + 'example' => 'functions', + ]) ->addRule('dateCreated', [ 'type' => self::TYPE_INTEGER, 'description' => 'The deployment creation date in Unix timestamp.', @@ -30,7 +36,7 @@ class Deployment extends Model ]) ->addRule('entrypoint', [ 'type' => self::TYPE_STRING, - 'description' => 'The entrypoint file to use to execute the delpoyment code.', + 'description' => 'The entrypoint file to use to execute the deployment code.', 'default' => '', 'example' => 'enabled', ]) @@ -40,35 +46,12 @@ class Deployment extends Model 'default' => 0, 'example' => 128, ]) - // Build Status - // Failed - The deployment build has failed. More details can usually be found in buildStderr - // Ready - The deployment build was successful and the deployment is ready to be deployed - // Processing - The deployment is currently waiting to have a build triggered - // Building - The deployment is currently being built - ->addRule('status', [ - 'type' => self::TYPE_STRING, - 'description' => 'The deployment\'s current built status', - 'default' => '', - 'example' => 'ready', - ]) ->addRule('buildId', [ 'type' => self::TYPE_STRING, 'description' => 'The current build ID.', 'default' => '', 'example' => '5e5ea5c16897e', ]) - ->addRule('buildStdout', [ - 'type' => self::TYPE_STRING, - 'description' => 'The stdout of the build.', - 'default' => '', - 'example' => '', - ]) - ->addRule('buildStderr', [ - 'type' => self::TYPE_STRING, - 'description' => 'The stderr of the build.', - 'default' => '', - 'example' => '', - ]) ->addRule('deploy', [ 'type' => self::TYPE_BOOLEAN, 'description' => 'Whether the deployment should be automatically deployed.',