From 3c17afbaed10eef8942c46d6baac86acb4cca41d Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Tue, 25 Jan 2022 16:51:05 +0000 Subject: [PATCH 01/24] Cleanup Collections - Rename functionId to resourceId on Deployments - Add a resourceType to Deployments - Remove status, buildStdout and buildStderr from deployments - Rename dateCreated on Builds to startTime - Rename time on Builds to endTime - Added a deploymentId to Builds - Added duration to builds - Remove Vars from Build --- app/config/collections.php | 75 ++++++++--------- app/controllers/api/functions.php | 29 +++---- app/executor.php | 81 ++++++++++--------- src/Appwrite/Utopia/Response/Model/Build.php | 16 +++- .../Utopia/Response/Model/Deployment.php | 35 +++----- 5 files changed, 109 insertions(+), 127 deletions(-) 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.', From d429aa180f72331f1b613e353fbe8ede6bfd380a Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 26 Jan 2022 10:09:11 +0000 Subject: [PATCH 02/24] Fix Build Structure in Executor --- app/executor.php | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/app/executor.php b/app/executor.php index 26711226f..3c92dc33b 100644 --- a/app/executor.php +++ b/app/executor.php @@ -673,6 +673,10 @@ function runBuildStage(string $buildId, string $projectID): Document // Check if build has already been run $build = $database->getDocument('builds', $buildId); + + // Start tracking time + $buildStart = \time(); + try { // If we already have a built package ready there is no need to rebuild. if ($build->getAttribute('status') === 'ready' && \file_exists($build->getAttribute('outputPath'))) { @@ -728,9 +732,6 @@ function runBuildStage(string $buildId, string $projectID): Document $vars = $build->getAttribute('vars', []); - // Start tracking time - $buildStart = \time(); - $orchestration ->setCpus(App::getEnv('_APP_FUNCTIONS_CPUS', 0)) ->setMemory(App::getEnv('_APP_FUNCTIONS_MEMORY', 256)) @@ -1084,23 +1085,17 @@ App::post('/v1/deployment') '$id' => $buildId, '$read' => (!empty($userId)) ? ['user:' . $userId] : [], '$write' => ['role:all'], - 'dateCreated' => time(), + 'startTime' => time(), 'status' => 'processing', + 'deploymentId' => $deploymentId, 'runtime' => $function->getAttribute('runtime'), 'outputPath' => '', 'source' => $deployment->getAttribute('path'), '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 ])); $deployment->setAttribute('buildId', $buildId); From 18e142089911c6ba434666674aecb43a98498711 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 26 Jan 2022 10:10:29 +0000 Subject: [PATCH 03/24] Update executor.php --- app/executor.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/executor.php b/app/executor.php index 3c92dc33b..cdc44cb56 100644 --- a/app/executor.php +++ b/app/executor.php @@ -1095,7 +1095,8 @@ App::post('/v1/deployment') 'stdout' => '', 'stderr' => '', 'endTime' => 0, - 'duration' => 0 + 'duration' => 0, + 'search' => implode(' ', [$deployment->getId(), $buildId]) ])); $deployment->setAttribute('buildId', $buildId); From 4113644fba35c828061a7a9e4bca5bf0fafc3e02 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 26 Jan 2022 10:23:30 +0000 Subject: [PATCH 04/24] Implement network environment variable for the executor. --- .env | 1 + Dockerfile | 1 + app/config/variables.php | 9 +++++++++ app/executor.php | 2 +- app/views/install/compose.phtml | 1 + docker-compose.yml | 1 + 6 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.env b/.env index 3f8e511b6..de41db626 100644 --- a/.env +++ b/.env @@ -40,6 +40,7 @@ _APP_FUNCTIONS_CPUS=4 _APP_FUNCTIONS_MEMORY=2000 _APP_FUNCTIONS_MEMORY_SWAP=2000 _APP_EXECUTOR_SECRET=a-randomly-generated-key +_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes _APP_MAINTENANCE_INTERVAL=86400 _APP_MAINTENANCE_RETENTION_EXECUTION=1209600 _APP_MAINTENANCE_RETENTION_ABUSE=86400 diff --git a/Dockerfile b/Dockerfile index 37f391fe2..19b9e6926 100755 --- a/Dockerfile +++ b/Dockerfile @@ -174,6 +174,7 @@ ENV _APP_SERVER=swoole \ _APP_FUNCTIONS_MEMORY=128 \ _APP_FUNCTIONS_MEMORY_SWAP=128 \ _APP_EXECUTOR_SECRET=a-random-secret \ + _APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes \ _APP_SETUP=self-hosted \ _APP_VERSION=$VERSION \ _APP_USAGE_STATS=enabled \ diff --git a/app/config/variables.php b/app/config/variables.php index 76dbf1cd5..93f124397 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -498,6 +498,15 @@ return [ 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_EXECUTOR_RUNTIME_NETWORK', + 'description' => 'The docker network used for communication between the executor and runtimes. Change this if you have altered the default network names.', + 'introduction' => '0.13.0', + 'default' => 'appwrite_runtimes', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_FUNCTIONS_ENVS', 'description' => 'Deprecated with 0.8.0, use \'_APP_FUNCTIONS_RUNTIMES\' instead!', diff --git a/app/executor.php b/app/executor.php index 59c5de8f0..74495e7d1 100644 --- a/app/executor.php +++ b/app/executor.php @@ -301,7 +301,7 @@ function createRuntimeServer(string $functionId, string $projectId, string $depl } // Add to network - $orchestration->networkConnect($container, 'appwrite_runtimes'); + $orchestration->networkConnect($container, App::getEnv('_APP_EXECUTOR_RUNTIME_NETWORK', 'appwrite_runtimes')); $executionEnd = \microtime(true); diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index a4e8aeb0c..f799a73e9 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -191,6 +191,7 @@ services: - _APP_FUNCTIONS_MEMORY - _APP_FUNCTIONS_MEMORY_SWAP - _APP_EXECUTOR_SECRET + - _APP_EXECUTOR_RUNTIME_NETWORK - _APP_USAGE_STATS - _APP_STATSD_HOST - _APP_STATSD_PORT diff --git a/docker-compose.yml b/docker-compose.yml index 4f7afc3d6..220ca8d14 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -391,6 +391,7 @@ services: - _APP_FUNCTIONS_MEMORY - _APP_FUNCTIONS_MEMORY_SWAP - _APP_EXECUTOR_SECRET + - _APP_EXECUTOR_RUNTIME_NETWORK - _APP_USAGE_STATS - _APP_STATSD_HOST - _APP_STATSD_PORT From f3e97e41334f20d4cae8e695103ff6ddf53681f7 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Wed, 26 Jan 2022 10:49:02 +0000 Subject: [PATCH 05/24] Fix environment variables during build --- app/config/collections.php | 44 +++++++++++++++++++------------------- app/executor.php | 20 ++++++++++++++++- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index 56883fc29..befcc5e06 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -2038,6 +2038,28 @@ $collections = [ 'array' => false, 'filters' => [], ], + [ + '$id' => 'endTime', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'duration', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], [ '$id' => 'deploymentId', 'type' => Database::VAR_STRING, @@ -2104,28 +2126,6 @@ $collections = [ 'array' => false, 'filters' => [], ], - [ - '$id' => 'endTime', - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => 'duration', - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], [ '$id' => 'sourceType', 'type' => Database::VAR_STRING, diff --git a/app/executor.php b/app/executor.php index cdc44cb56..f0ca068a2 100644 --- a/app/executor.php +++ b/app/executor.php @@ -730,7 +730,25 @@ 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', []); $orchestration ->setCpus(App::getEnv('_APP_FUNCTIONS_CPUS', 0)) From c94b28555df46f0d12b1c3be1fb84abbba866e52 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 27 Jan 2022 09:18:01 +0000 Subject: [PATCH 06/24] Remove Try Catch's and use global handler --- app/executor.php | 225 ++++++++++++++++++++--------------------------- 1 file changed, 97 insertions(+), 128 deletions(-) diff --git a/app/executor.php b/app/executor.php index 59c5de8f0..1c7d49f84 100644 --- a/app/executor.php +++ b/app/executor.php @@ -915,32 +915,24 @@ function runBuildStage(string $buildId, string $projectID): Document App::post('/v1/execute') // Define Route ->desc('Execute a function') - ->param('trigger', '', new Text(1024)) - ->param('projectId', '', new Text(1024)) - ->param('executionId', '', new Text(1024), '', true) - ->param('functionId', '', new Text(1024)) - ->param('event', '', new Text(1024), '', true) - ->param('eventData', '', new Text(10240), '', true) - ->param('data', '', new Text(1024), '', true) - ->param('webhooks', [], new ArrayList(new JSON()), '', true) - ->param('userId', '', new Text(1024), '', true) - ->param('jwt', '', new Text(1024), '', true) + ->param('trigger', '', new Text(1024), 'What triggered this execution, can be http / schedule / event') + ->param('projectId', '', new Text(1024), 'The ProjectID this execution belongs to') + ->param('executionId', '', new Text(1024), 'An optional execution ID, If not specified a new execution document is created.', true) + ->param('functionId', '', new Text(1024), 'The FunctionID to execute') + ->param('event', '', new Text(1024), 'The event that triggered this execution', true) + ->param('eventData', '', new Text(0), 'Extra Data for the event', true) + ->param('data', '', new Text(1024), 'Data to be forwarded to the function, this is user specified.', true) + ->param('webhooks', [], new ArrayList(new JSON()), 'Any webhooks that need to be triggered after this execution', true) + ->param('userId', '', new Text(1024), 'The UserID of the user who triggered the execution if it was called from a client SDK', true) + ->param('jwt', '', new Text(1024), 'A JWT of the user who triggered the execution if it was called from a client SDK', true) ->inject('response') ->inject('dbForProject') ->action( function (string $trigger, string $projectId, string $executionId, string $functionId, string $event, string $eventData, string $data, array $webhooks, string $userId, string $jwt, Response $response, Database $dbForProject) { - try { - $data = execute($trigger, $projectId, $executionId, $functionId, $dbForProject, $event, $eventData, $data, $webhooks, $userId, $jwt); - $response->json($data); - } catch (Exception $e) { - logError($e, 'executeEndpoint'); + $data = execute($trigger, $projectId, $executionId, $functionId, $dbForProject, $event, $eventData, $data, $webhooks, $userId, $jwt); - $response - ->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') - ->addHeader('Expires', '0') - ->addHeader('Pragma', 'no-cache') - ->json(['error' => $e->getMessage()]); - } + $response->setStatusCode(Response::STATUS_CODE_OK); + $response->json($data); } ); @@ -951,10 +943,9 @@ App::post('/v1/cleanup/function') ->inject('dbForProject') ->action( function (string $functionId, Response $response, Database $dbForProject) use ($orchestrationPool) { + /** @var Orchestration $orchestration */ + $orchestration = $orchestrationPool->get(); try { - /** @var Orchestration $orchestration */ - $orchestration = $orchestrationPool->get(); - // Get function document $function = $dbForProject->getDocument('functions', $functionId); @@ -967,38 +958,35 @@ App::post('/v1/cleanup/function') // If amount is 0 then we simply return true if (count($results) === 0) { + $response->setStatusCode(Response::STATUS_CODE_OK); return $response->json(['success' => true]); } // Delete the containers of all deployments foreach ($results as $deployment) { - try { - // Remove any ongoing builds - if ($deployment->getAttribute('buildId')) { - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId')); + // Remove any ongoing builds + if ($deployment->getAttribute('buildId')) { + $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId')); - if ($build->getAttribute('status') === 'building') { - // Remove the build - $orchestration->remove('build-stage-' . $deployment->getAttribute('buildId'), true); - Console::info('Removed build for deployment ' . $deployment['$id']); - } + if ($build->getAttribute('status') === 'building') { + // Remove the build + $orchestration->remove('build-stage-' . $deployment->getAttribute('buildId'), true); + Console::info('Removed build for deployment ' . $deployment['$id']); } - - $orchestration->remove('appwrite-function-' . $deployment['$id'], true); - Console::info('Removed container for deployment ' . $deployment['$id']); - } catch (Exception $e) { - // Do nothing, we don't care that much if it fails } + + $orchestration->remove('appwrite-function-' . $deployment['$id'], true); + Console::info('Removed container for deployment ' . $deployment['$id']); } + $response->setStatusCode(Response::STATUS_CODE_OK); return $response->json(['success' => true]); - } catch (Exception $e) { - logError($e, "cleanupFunction"); + } catch (Throwable $th) { + $orchestrationPool->put($orchestration); + throw $th; + } finally { $orchestrationPool->put($orchestration); - - return $response->json(['error' => $e->getMessage()]); } - $orchestrationPool->put($orchestration); } ); @@ -1007,10 +995,9 @@ App::post('/v1/cleanup/deployment') ->inject('response') ->inject('dbForProject') ->action(function (string $deploymentId, Response $response, Database $dbForProject) use ($orchestrationPool) { + /** @var Orchestration $orchestration */ + $orchestration = $orchestrationPool->get(); try { - /** @var Orchestration $orchestration */ - $orchestration = $orchestrationPool->get(); - // Get deployment document $deployment = $dbForProject->getDocument('deployments', $deploymentId); @@ -1019,29 +1006,23 @@ App::post('/v1/cleanup/deployment') throw new Exception('Deployment not found', 404); } - try { - // Remove any ongoing builds - if ($deployment->getAttribute('buildId')) { - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId')); + // Remove any ongoing builds + if ($deployment->getAttribute('buildId')) { + $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId')); - if ($build->getAttribute('status') == 'building') { - // Remove the build - $orchestration->remove('build-stage-' . $deployment->getAttribute('buildId'), true); - Console::info('Removed build for deployment ' . $deployment['$id']); - } + if ($build->getAttribute('status') == 'building') { + // Remove the build + $orchestration->remove('build-stage-' . $deployment->getAttribute('buildId'), true); + Console::info('Removed build for deployment ' . $deployment['$id']); } - - // Remove the container of the deployment - $orchestration->remove('appwrite-function-' . $deployment['$id'], true); - Console::info('Removed container for deployment ' . $deployment['$id']); - } catch (Exception $e) { - // Do nothing, we don't care that much if it fails } - } catch (Exception $e) { - logError($e, "cleanupFunction"); - $orchestrationPool->put($orchestration); - return $response->json(['error' => $e->getMessage()]); + // Remove the container of the deployment + $orchestration->remove('appwrite-function-' . $deployment['$id'], true); + Console::info('Removed container for deployment ' . $deployment['$id']); + } catch (Throwable $th) { + $orchestrationPool->put($orchestration); + throw $th; } $orchestrationPool->put($orchestration); @@ -1074,7 +1055,7 @@ App::post('/v1/deployment') $runtime = $runtimes[$function->getAttribute('runtime')] ?? null; if (\is_null($runtime)) { - throw new Exception('Runtime "' . $function->getAttribute('runtime', '') . '" is not supported'); + throw new Exception('Runtime "' . $function->getAttribute('runtime', '') . '" is not supported', 404); } // Create a new build entry @@ -1083,37 +1064,32 @@ App::post('/v1/deployment') if ($deployment->getAttribute('buildId')) { $buildId = $deployment->getAttribute('buildId'); } else { - try { - $dbForProject->createDocument('builds', new Document([ - '$id' => $buildId, - '$read' => (!empty($userId)) ? ['user:' . $userId] : [], - '$write' => ['role:all'], - 'dateCreated' => time(), - 'status' => 'processing', - 'runtime' => $function->getAttribute('runtime'), - 'outputPath' => '', - 'source' => $deployment->getAttribute('path'), - '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, - ] - ])); + $dbForProject->createDocument('builds', new Document([ + '$id' => $buildId, + '$read' => (!empty($userId)) ? ['user:' . $userId] : [], + '$write' => ['role:all'], + 'dateCreated' => time(), + 'status' => 'processing', + 'runtime' => $function->getAttribute('runtime'), + 'outputPath' => '', + 'source' => $deployment->getAttribute('path'), + '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, + ] + ])); - $deployment->setAttribute('buildId', $buildId); + $deployment->setAttribute('buildId', $buildId); - $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - } catch (\Throwable $th) { - var_dump($deployment->getArrayCopy()); - throw $th; - } + $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); } // Build Code @@ -1156,6 +1132,9 @@ App::post('/v1/deployment') // Deploy Runtime Server createRuntimeServer($functionId, $projectID, $deploymentId, $dbForProject); } catch (\Throwable $th) { + $register->get('dbPool')->put($db); + $register->get('redisPool')->put($redis); + throw $th; } finally { $register->get('dbPool')->put($db); $register->get('redisPool')->put($redis); @@ -1188,41 +1167,31 @@ App::post('/v1/build/:buildId') // Start a Build ->inject('dbForProject') ->inject('projectID') ->action(function (string $buildId, Response $response, Database $dbForProject, string $projectID) { - try { - // Get build document - $build = $dbForProject->getDocument('builds', $buildId); + // Get build document + $build = $dbForProject->getDocument('builds', $buildId); - // Check if build exists - if ($build->isEmpty()) { - throw new Exception('Build not found', 404); - } - - // Check if build is already running - if ($build->getAttribute('status') === 'running') { - throw new Exception('Build is already running', 409); - } - - // Check if build is already finished - if ($build->getAttribute('status') === 'finished') { - throw new Exception('Build is already finished', 409); - } - - go(function () use ($buildId, $dbForProject, $projectID) { - // Build Code - runBuildStage($buildId, $projectID, $dbForProject); - }); - - // return success - return $response->json(['success' => true]); - } catch (Exception $e) { - logError($e, "buildEndpoint"); - - $response - ->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') - ->addHeader('Expires', '0') - ->addHeader('Pragma', 'no-cache') - ->json(['error' => $e->getMessage()]); + // Check if build exists + if ($build->isEmpty()) { + throw new Exception('Build not found', 404); } + + // Check if build is already running + if ($build->getAttribute('status') === 'running') { + throw new Exception('Build is already running', 409); + } + + // Check if build is already finished + if ($build->getAttribute('status') === 'finished') { + throw new Exception('Build is already finished', 409); + } + + go(function () use ($buildId, $dbForProject, $projectID) { + // Build Code + runBuildStage($buildId, $projectID, $dbForProject); + }); + + // return success + return $response->json(['success' => true]); }); App::setMode(App::MODE_TYPE_PRODUCTION); // Define Mode From 7d3f992a9f1b494dcae5d3e449ed5c978b400aed Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 27 Jan 2022 09:18:48 +0000 Subject: [PATCH 07/24] Add status codes --- app/executor.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/executor.php b/app/executor.php index 1c7d49f84..a509ba1ef 100644 --- a/app/executor.php +++ b/app/executor.php @@ -1026,6 +1026,7 @@ App::post('/v1/cleanup/deployment') } $orchestrationPool->put($orchestration); + $response->setStatusCode(Response::STATUS_CODE_OK); return $response->json(['success' => true]); }); @@ -1191,6 +1192,7 @@ App::post('/v1/build/:buildId') // Start a Build }); // return success + $response->setStatusCode(Response::STATUS_CODE_OK); return $response->json(['success' => true]); }); From d8a9b7e933f294993d4e5d6b2d589b953fc06c44 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 27 Jan 2022 09:27:57 +0000 Subject: [PATCH 08/24] More cleaning up --- app/executor.php | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/app/executor.php b/app/executor.php index a509ba1ef..9b22be1f4 100644 --- a/app/executor.php +++ b/app/executor.php @@ -25,7 +25,6 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Logger\Log; -use Utopia\Orchestration\Adapter\DockerAPI; use Utopia\Orchestration\Adapter\DockerCLI; use Utopia\Orchestration\Orchestration; use Utopia\Registry\Registry; @@ -931,14 +930,15 @@ App::post('/v1/execute') // Define Route function (string $trigger, string $projectId, string $executionId, string $functionId, string $event, string $eventData, string $data, array $webhooks, string $userId, string $jwt, Response $response, Database $dbForProject) { $data = execute($trigger, $projectId, $executionId, $functionId, $dbForProject, $event, $eventData, $data, $webhooks, $userId, $jwt); - $response->setStatusCode(Response::STATUS_CODE_OK); - $response->json($data); + return $response + ->setStatusCode(Response::STATUS_CODE_OK) + ->json($data); } ); // Cleanup Endpoints used internally by appwrite when a function or deployment gets deleted to also clean up their containers App::post('/v1/cleanup/function') - ->param('functionId', '', new UID()) + ->param('functionId', '', new UID(), 'The FunctionID to cleanup') ->inject('response') ->inject('dbForProject') ->action( @@ -958,8 +958,9 @@ App::post('/v1/cleanup/function') // If amount is 0 then we simply return true if (count($results) === 0) { - $response->setStatusCode(Response::STATUS_CODE_OK); - return $response->json(['success' => true]); + return $response + ->setStatusCode(Response::STATUS_CODE_OK) + ->json(['success' => true]); } // Delete the containers of all deployments @@ -979,8 +980,9 @@ App::post('/v1/cleanup/function') Console::info('Removed container for deployment ' . $deployment['$id']); } - $response->setStatusCode(Response::STATUS_CODE_OK); - return $response->json(['success' => true]); + return $response + ->setStatusCode(Response::STATUS_CODE_OK) + ->json(['success' => true]); } catch (Throwable $th) { $orchestrationPool->put($orchestration); throw $th; @@ -1026,8 +1028,9 @@ App::post('/v1/cleanup/deployment') } $orchestrationPool->put($orchestration); - $response->setStatusCode(Response::STATUS_CODE_OK); - return $response->json(['success' => true]); + return $response + ->setStatusCode(Response::STATUS_CODE_OK) + ->json(['success' => true]); }); App::post('/v1/deployment') @@ -1149,17 +1152,6 @@ App::post('/v1/deployment') $response->dynamic($function, Response::MODEL_FUNCTION); }); -App::get('/v1/') - ->inject('response') - ->action( - function (Response $response) { - $response - ->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') - ->addHeader('Expires', '0') - ->addHeader('Pragma', 'no-cache') - ->json(['status' => 'online']); - } - ); // Build Endpoints App::post('/v1/build/:buildId') // Start a Build @@ -1192,8 +1184,9 @@ App::post('/v1/build/:buildId') // Start a Build }); // return success - $response->setStatusCode(Response::STATUS_CODE_OK); - return $response->json(['success' => true]); + return $response + ->setStatusCode(Response::STATUS_CODE_OK) + ->json(['success' => true]); }); App::setMode(App::MODE_TYPE_PRODUCTION); // Define Mode From 8f51bf47630bc8c68274ed7d6803295504568245 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 28 Jan 2022 16:29:06 +0400 Subject: [PATCH 09/24] feat: linting --- app/controllers/api/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 47cae1cec..0ae254f9b 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -588,7 +588,7 @@ App::post('/v1/functions/:functionId/deployments') ]); $usage - ->setParam('storage', $deployment->getAttribute('size', 0)) + ->setParam('storage', $deployment->getAttribute('size', 0)) ; From 1f95e649473cf460395e033d864d48e0b4f664ca Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 28 Jan 2022 16:30:19 +0400 Subject: [PATCH 10/24] feat: replace var_dump --- app/executor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/executor.php b/app/executor.php index 3bd6eb5f4..135018fd2 100644 --- a/app/executor.php +++ b/app/executor.php @@ -317,7 +317,7 @@ function createRuntimeServer(string $functionId, string $projectId, string $depl Console::success('Runtime server is ready to run'); } } catch (\Throwable $th) { - var_dump($th->getTraceAsString()); + Console::error($th->getMessage()); $orchestrationPool->put($orchestration ?? null); throw $th; } From 150e35244b1c56b06c7efd2f6161fe3194b494e6 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 28 Jan 2022 16:31:41 +0400 Subject: [PATCH 11/24] feat: remove executor port --- docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 1ad9d203f..a0e62e108 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -384,8 +384,6 @@ services: - /usr/src/code/app/executor.php - -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php stop_signal: SIGINT - ports: - - "8080:8080" build: context: . args: From fa006e9963a323e9c813133b4b681903b92801e9 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Mon, 31 Jan 2022 13:46:24 +0400 Subject: [PATCH 12/24] feat: replace strings with constant --- app/controllers/api/functions.php | 5 +++-- src/Appwrite/Event/Event.php | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 0ae254f9b..f30adfc09 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -3,6 +3,7 @@ use Ahc\Jwt\JWT; use Appwrite\Auth\Auth; use Appwrite\Database\Validator\CustomId; +use Appwrite\Event\Event; use Utopia\Database\Validator\UID; use Utopia\Storage\Storage; use Utopia\Storage\Validator\File; @@ -580,7 +581,7 @@ App::post('/v1/functions/:functionId/deployments') ])); // Enqueue a message to start the build - Resque::enqueue('v1-builds', 'BuildsV1', [ + Resque::enqueue(Event::BUILDS_QUEUE_NAME, Event::BUILDS_CLASS_NAME, [ 'projectId' => $project->getId(), 'functionId' => $function->getId(), 'deploymentId' => $deploymentId, @@ -1121,7 +1122,7 @@ App::post('/v1/builds/:buildId') } // Enqueue a message to start the build - Resque::enqueue('v1-builds', 'BuildsV1', [ + Resque::enqueue(Event::BUILDS_QUEUE_NAME, Event::BUILDS_CLASS_NAME, [ 'projectId' => $project->getId(), 'buildId' => $buildId, 'type' => BUILD_TYPE_RETRY diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index a367e0790..2bd73248c 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -30,6 +30,9 @@ class Event const CERTIFICATES_QUEUE_NAME = 'v1-certificates'; const CERTIFICATES_CLASS_NAME = 'CertificatesV1'; + + const BUILDS_QUEUE_NAME = 'v1-builds'; + const BUILDS_CLASS_NAME = 'BuildsV1'; /** * @var string From 43050415678459e2dbaa97cadc11c19b4ef82675 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Mon, 31 Jan 2022 13:51:12 +0400 Subject: [PATCH 13/24] feat: add builds worker in installation docker-compose --- app/views/install/compose.phtml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index a4e8aeb0c..4269afb1a 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -221,6 +221,34 @@ services: - _APP_DB_USER - _APP_DB_PASS + appwrite-worker-builds: + image: /: + entrypoint: worker-builds + container_name: appwrite-worker-builds + restart: unless-stopped + networks: + - appwrite + volumes: + - ./app:/usr/src/code/app + - ./src:/usr/src/code/src + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_EXECUTOR_SECRET + appwrite-worker-audits: image: /: entrypoint: worker-audits From b9dfb8188aa73ded4508894bafdb4e894f26b2f0 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Mon, 31 Jan 2022 14:06:15 +0400 Subject: [PATCH 14/24] feat: add builds worker to test docker-compose --- tests/resources/docker/docker-compose.yml | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/resources/docker/docker-compose.yml b/tests/resources/docker/docker-compose.yml index 76d62317a..395557372 100644 --- a/tests/resources/docker/docker-compose.yml +++ b/tests/resources/docker/docker-compose.yml @@ -266,6 +266,34 @@ services: - _APP_REDIS_PORT - _APP_SMTP_HOST - _APP_SMTP_PORT + + appwrite-worker-builds: + entrypoint: worker-builds + container_name: appwrite-worker-builds + build: + context: . + networks: + - appwrite + volumes: + - ./app:/usr/src/code/app + - ./src:/usr/src/code/src + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_LOGGING_PROVIDER + - _APP_LOGGING_CONFIG + - _APP_EXECUTOR_SECRET appwrite-schedule: entrypoint: schedule From ce6e14a7cce1cae8357aa176b43e02cb4cbdea57 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Mon, 31 Jan 2022 14:14:55 +0400 Subject: [PATCH 15/24] feat: add builds worker to test docker-compose --- app/views/install/compose.phtml | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 4269afb1a..fbe2f0fee 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -228,9 +228,6 @@ services: restart: unless-stopped networks: - appwrite - volumes: - - ./app:/usr/src/code/app - - ./src:/usr/src/code/src depends_on: - redis - mariadb From fc6e7739ded3b71d9b062245ff0c8a56af66c763 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Mon, 31 Jan 2022 14:30:55 +0400 Subject: [PATCH 16/24] feat: review comments --- app/executor.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/executor.php b/app/executor.php index c78ef63d5..d280f408e 100644 --- a/app/executor.php +++ b/app/executor.php @@ -936,7 +936,6 @@ App::post('/v1/functions/:functionId/executions') ->action( function (string $trigger, string $projectId, string $executionId, string $functionId, string $event, string $eventData, string $data, array $webhooks, string $userId, string $jwt, Response $response, Database $dbForProject) { $data = execute($trigger, $projectId, $executionId, $functionId, $dbForProject, $event, $eventData, $data, $webhooks, $userId, $jwt); - $response ->setStatusCode(Response::STATUS_CODE_OK) ->json($data); @@ -950,9 +949,10 @@ App::delete('/v1/functions/:functionId') ->inject('dbForProject') ->action( function (string $functionId, Response $response, Database $dbForProject) use ($orchestrationPool) { - /** @var Orchestration $orchestration */ - $orchestration = $orchestrationPool->get(); try { + /** @var Orchestration $orchestration */ + $orchestration = $orchestrationPool->get(); + // Get function document $function = $dbForProject->getDocument('functions', $functionId); @@ -1037,9 +1037,10 @@ App::delete('/v1/deployments/:deploymentId') ->inject('response') ->inject('dbForProject') ->action(function (string $deploymentId, Response $response, Database $dbForProject) use ($orchestrationPool) { - /** @var Orchestration $orchestration */ - $orchestration = $orchestrationPool->get(); try { + /** @var Orchestration $orchestration */ + $orchestration = $orchestrationPool->get(); + // Get deployment document $deployment = $dbForProject->getDocument('deployments', $deploymentId); From 6b77d62e4b700b23258409f59899d676e502e4ac Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 31 Jan 2022 10:46:52 +0000 Subject: [PATCH 17/24] Update app/executor.php Co-authored-by: Christy Jacob --- app/executor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/executor.php b/app/executor.php index d280f408e..e15a505f5 100644 --- a/app/executor.php +++ b/app/executor.php @@ -1069,9 +1069,9 @@ App::delete('/v1/deployments/:deploymentId') } $orchestrationPool->put($orchestration); - return $response + $response ->setStatusCode(Response::STATUS_CODE_OK) - ->json(['success' => true]); + ->send(); }); App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId') From 663ce27db4f631d7a33a68c484395a803d8d93ad Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 31 Jan 2022 10:47:00 +0000 Subject: [PATCH 18/24] Update app/executor.php Co-authored-by: Christy Jacob --- app/executor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/executor.php b/app/executor.php index e15a505f5..4e3058ebc 100644 --- a/app/executor.php +++ b/app/executor.php @@ -987,9 +987,9 @@ App::delete('/v1/functions/:functionId') Console::info('Removed container for deployment ' . $deployment['$id']); } - return $response + $response ->setStatusCode(Response::STATUS_CODE_OK) - ->json(['success' => true]); + ->send(); } catch (Throwable $th) { $orchestrationPool->put($orchestration); throw $th; From 30a567058ab859dbca2c939959fbbcc79f0f1d71 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 31 Jan 2022 10:47:04 +0000 Subject: [PATCH 19/24] Update app/executor.php Co-authored-by: Christy Jacob --- app/executor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/executor.php b/app/executor.php index 4e3058ebc..bc5ddc9e6 100644 --- a/app/executor.php +++ b/app/executor.php @@ -965,9 +965,9 @@ App::delete('/v1/functions/:functionId') // If amount is 0 then we simply return true if (count($results) === 0) { - return $response + $response ->setStatusCode(Response::STATUS_CODE_OK) - ->json(['success' => true]); + ->send(); } // Delete the containers of all deployments From a47211e7eeb953e85bd6a5f88d50d6b166c6dde5 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 31 Jan 2022 10:57:57 +0000 Subject: [PATCH 20/24] Update executor.php --- app/executor.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/executor.php b/app/executor.php index 9b22be1f4..d16cb4ce0 100644 --- a/app/executor.php +++ b/app/executor.php @@ -363,7 +363,7 @@ function execute(string $trigger, string $projectId, string $executionId, string } - if ($build->getAttribute('status') == 'building') { + if ($build->getAttribute('status') === 'building') { $execution ->setAttribute('status', 'failed') @@ -632,7 +632,7 @@ function execute(string $trigger, string $projectId, string $executionId, string roles: $target['roles'] ); - if (App::getEnv('_APP_USAGE_STATS', 'enabled') == 'enabled') { + if (App::getEnv('_APP_USAGE_STATS', 'enabled') === 'enabled') { $statsd = $register->get('statsd'); $usage = new Stats($statsd); @@ -652,7 +652,7 @@ function execute(string $trigger, string $projectId, string $executionId, string return [ 'status' => $functionStatus, - 'response' => ($functionStatus !== 'completed') ? $stderr : $stdout, + 'response' => ($functionStatus !=== 'completed') ? $stderr : $stdout, 'time' => $executionTime ]; }; @@ -868,7 +868,7 @@ function runBuildStage(string $buildId, string $projectID): Document } } - if ($buildStdout == '') { + if ($buildStdout === '') { $buildStdout = 'Build Successful!'; } @@ -1012,7 +1012,7 @@ App::post('/v1/cleanup/deployment') if ($deployment->getAttribute('buildId')) { $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId')); - if ($build->getAttribute('status') == 'building') { + if ($build->getAttribute('status') === 'building') { // Remove the build $orchestration->remove('build-stage-' . $deployment->getAttribute('buildId'), true); Console::info('Removed build for deployment ' . $deployment['$id']); From 8e639d4f5f85526928596e5a2c921d5a83afdedf Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 31 Jan 2022 11:29:31 +0000 Subject: [PATCH 21/24] Fix UI --- app/controllers/api/functions.php | 7 +++++++ .../Utopia/Response/Model/Deployment.php | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 47d6c1bd0..ddfe50cda 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -675,6 +675,13 @@ App::get('/v1/functions/:functionId/deployments') $results = $dbForProject->find('deployments', $queries, $limit, $offset, [], [$orderType], $cursorDeployment ?? null, $cursorDirection); $sum = $dbForProject->count('deployments', $queries, APP_LIMIT_COUNT); + foreach ($results as $result) { + $build = $dbForProject->getDocument('builds', $result->getAttribute('buildId')); + $result->setAttribute('status', $build->getAttribute('status', 'pending')); + $result->setAttribute('buildStderr', $build->getAttribute('stderr', '')); + $result->setAttribute('buildStdout', $build->getAttribute('stdout', '')); + } + $response->dynamic(new Document([ 'deployments' => $results, 'sum' => $sum, diff --git a/src/Appwrite/Utopia/Response/Model/Deployment.php b/src/Appwrite/Utopia/Response/Model/Deployment.php index b3ecf0290..28a01ad6c 100644 --- a/src/Appwrite/Utopia/Response/Model/Deployment.php +++ b/src/Appwrite/Utopia/Response/Model/Deployment.php @@ -58,6 +58,24 @@ class Deployment extends Model 'default' => false, 'example' => true, ]) + ->addRule('status', [ + 'type' => self::TYPE_STRING, + 'description' => 'The deployment status.', + 'default' => '', + 'example' => 'enabled', + ]) + ->addRule('buildStdout', [ + 'type' => self::TYPE_STRING, + 'description' => 'The build stdout.', + 'default' => '', + 'example' => 'enabled', + ]) + ->addRule('buildStderr', [ + 'type' => self::TYPE_STRING, + 'description' => 'The build stderr.', + 'default' => '', + 'example' => 'enabled', + ]) ; } From d2ec314ef0733b1803d53a7f5fbc51d21900d5d6 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 31 Jan 2022 11:36:22 +0000 Subject: [PATCH 22/24] Remove Search and add resourceType to indexes --- app/config/collections.php | 20 ++++----- app/controllers/api/functions.php | 71 ------------------------------- app/executor.php | 6 +-- 3 files changed, 10 insertions(+), 87 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index befcc5e06..b8b0afdea 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -2012,6 +2012,13 @@ $collections = [ 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], ], + [ + '$id' => '_key_resource_type', + 'type' => Database::INDEX_KEY, + 'attributes' => ['resourceType'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], [ '$id' => '_key_search', 'type' => Database::INDEX_FULLTEXT, @@ -2147,18 +2154,7 @@ $collections = [ 'default' => '', 'array' => false, 'filters' => [], - ], - [ - '$id' => 'search', - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], + ] ], 'indexes' => [ [ diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index ddfe50cda..db0950c43 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -1052,77 +1052,6 @@ App::get('/v1/functions/:functionId/executions/:executionId') $response->dynamic($execution, Response::MODEL_EXECUTION); }); -App::get('/v1/builds') -->groups(['api', 'functions']) -->desc('List Builds') -->label('scope', 'functions.read') -->label('sdk.auth', [APP_AUTH_TYPE_KEY]) -->label('sdk.namespace', 'functions') -->label('sdk.method', 'builds') -->label('sdk.description', '/docs/references/functions/list-builds.md') -->label('sdk.response.code', Response::STATUS_CODE_OK) -->label('sdk.response.type', Response::CONTENT_TYPE_JSON) -->label('sdk.response.model', Response::MODEL_BUILD_LIST) -->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) -->param('limit', 25, new Range(0, 100), 'Maximum number of builds to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) -->param('offset', 0, new Range(0, APP_LIMIT_COUNT), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)', true) -->param('cursor', '', new UID(), 'ID of the function used as the starting point for the query, excluding the function itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)', true) -->param('cursorDirection', Database::CURSOR_AFTER, new WhiteList([Database::CURSOR_AFTER, Database::CURSOR_BEFORE]), 'Direction of the cursor.', true) -->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) -->inject('response') -->inject('dbForProject') -->action(function ($search, $limit, $offset, $cursor, $cursorDirection, $orderType, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - - if (!empty($cursor)) { - $cursorFunction = $dbForProject->getDocument('builds', $cursor); - - if ($cursorFunction->isEmpty()) { - throw new Exception("Build '{$cursor}' for the 'cursor' value not found.", 400); - } - } - - $queries = []; - - if (!empty($search)) { - $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); - } - - $response->dynamic(new Document([ - 'builds' => $dbForProject->find('builds', $queries, $limit, $offset, [], [$orderType], $cursorFunction ?? null, $cursorDirection), - 'sum' => $dbForProject->count('builds', $queries, APP_LIMIT_COUNT), - ]), Response::MODEL_BUILD_LIST); -}); - -App::get('/v1/builds/:buildId') - ->groups(['api', 'functions']) - ->desc('Get Build') - ->label('scope', 'execution.read') - ->label('sdk.auth', [APP_AUTH_TYPE_SESSION, APP_AUTH_TYPE_KEY, APP_AUTH_TYPE_JWT]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getBuild') - ->label('sdk.description', '/docs/references/functions/get-build.md') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_BUILD) - ->param('buildId', '', new UID(), 'Build unique ID.') - ->inject('response') - ->inject('dbForProject') - ->action(function ($buildId, $response, $dbForProject) { - /** @var Appwrite\Utopia\Response $response */ - /** @var Utopia\Database\Database $dbForProject */ - - $build = Authorization::skip(function () use ($dbForProject, $buildId) { - return $dbForProject->getDocument('builds', $buildId); - }); - - if ($build->isEmpty()) { - throw new Exception('Build not found', 404); - } - - $response->dynamic($build, Response::MODEL_BUILD); - }); App::post('/v1/builds/:buildId') ->groups(['api', 'functions']) ->desc('Retry Build') diff --git a/app/executor.php b/app/executor.php index f0ca068a2..8d9d593f1 100644 --- a/app/executor.php +++ b/app/executor.php @@ -420,8 +420,7 @@ function execute(string $trigger, string $projectId, string $executionId, string 'stdout' => '', 'stderr' => '', 'endTime' => 0, - 'duration' => 0, - 'search' => implode(' ', [$deployment->getId(), $buildId]), + 'duration' => 0 ])); $deployment->setAttribute('buildId', $buildId); @@ -1113,8 +1112,7 @@ App::post('/v1/deployment') 'stdout' => '', 'stderr' => '', 'endTime' => 0, - 'duration' => 0, - 'search' => implode(' ', [$deployment->getId(), $buildId]) + 'duration' => 0 ])); $deployment->setAttribute('buildId', $buildId); From 83e9e9f0164c22c458f6257ca4edeaa9fe5a15bb Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Mon, 31 Jan 2022 15:57:55 +0400 Subject: [PATCH 23/24] feat: remove search index and updates tests --- app/config/collections.php | 9 +----- .../Functions/FunctionsCustomServerTest.php | 32 ------------------- 2 files changed, 1 insertion(+), 40 deletions(-) diff --git a/app/config/collections.php b/app/config/collections.php index b8b0afdea..15471c8c7 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -2163,14 +2163,7 @@ $collections = [ 'attributes' => ['status'], 'lengths' => [Database::LENGTH_KEY], 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => '_key_search', - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [2048], - 'orders' => [Database::ORDER_ASC], - ], + ] ], ], diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index a9e9096fe..ce220806b 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -331,38 +331,6 @@ class FunctionsCustomServerTest extends Scope return $data; } - /** - * @depends testCreateDeployment - */ - public function testListBuild(array $data):array - { - /** - * Test for SUCCESS - */ - $response = $this->client->call(Client::METHOD_GET, '/builds', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(1, $response['body']['sum']); - $this->assertEquals($response['body']['builds'][0]['status'], 'ready'); - - /** - * Check Queries work - */ - $responseQuery = $this->client->call(Client::METHOD_GET, '/builds?status=status.equal(\"ready\")', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - - $this->assertEquals(200, $responseQuery['headers']['status-code']); - $this->assertEquals(1, $responseQuery['body']['sum']); - $this->assertEquals($responseQuery['body']['builds'][0]['status'], 'ready'); - - return $data; - } - /** * @depends testCreateDeployment */ From 52c39d87841eeb1606db4a6839282740e5497cea Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Mon, 31 Jan 2022 13:38:06 +0000 Subject: [PATCH 24/24] Fix Executor --- app/executor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/executor.php b/app/executor.php index 5dcf849b4..2e966055f 100644 --- a/app/executor.php +++ b/app/executor.php @@ -653,7 +653,7 @@ function execute(string $trigger, string $projectId, string $executionId, string return [ 'status' => $functionStatus, - 'response' => ($functionStatus !=== 'completed') ? $stderr : $stdout, + 'response' => ($functionStatus !== 'completed') ? $stderr : $stdout, 'time' => $executionTime ]; };