From eb8543c6907f660c8ea8f9fa4f54e33a0342a63d Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Mon, 1 Apr 2024 17:04:36 +0530 Subject: [PATCH 1/6] Create failed execution if deployment doesn't exist --- src/Appwrite/Platform/Workers/Functions.php | 58 ++++++++++++++++++--- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index bde5644ade..e7f28a8dcb 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -194,6 +194,51 @@ class Functions extends Action } } + /** + * @param Document $function + * @param string $trigger + * @param string $path + * @param string $method + * @param Document $user + * @throws Exception + */ + private function fail( + Database $dbForProject, + Document $function, + string $trigger, + string $path, + string $method, + Document $user, + ): void { + $executionId = ID::unique(); + $execution = new Document([ + '$id' => $executionId, + '$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))], + 'functionInternalId' => $function->getInternalId(), + 'functionId' => $function->getId(), + 'deploymentInternalId' => '', + 'deploymentId' => '', + 'trigger' => $trigger, + 'status' => 'failed', + 'responseStatusCode' => 400, + 'responseHeaders' => [], + 'requestPath' => $path, + 'requestMethod' => $method, + 'errors' => 'Deployment not found. Create deployment before trying to execute a function.', + 'logs' => '', + 'duration' => 0.0, + 'search' => implode(' ', [$function->getId(), $executionId]), + ]); + + if ($function->getAttribute('logging')) { + $execution = $dbForProject->createDocument('executions', $execution); + } + + if ($execution->isEmpty()) { + throw new Exception('Failed to create execution'); + } + } + /** * @param Log $log * @param Database $dbForProject @@ -248,15 +293,17 @@ class Functions extends Action $deployment = $dbForProject->getDocument('deployments', $deploymentId); if ($deployment->getAttribute('resourceId') !== $functionId) { - throw new Exception('Deployment not found. Create deployment before trying to execute a function'); + $this->fail($dbForProject, $function, $trigger, $path, $method, $user); + return; } if ($deployment->isEmpty()) { - throw new Exception('Deployment not found. Create deployment before trying to execute a function'); + $this->fail($dbForProject, $function, $trigger, $path, $method, $user); + return; } - /** Check if build has exists */ - $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); + /** Check if the build exists */ + $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); if ($build->isEmpty()) { throw new Exception('Build not found'); } @@ -265,7 +312,7 @@ class Functions extends Action throw new Exception('Build not ready'); } - /** Check if runtime is supported */ + /** Check if runtime is supported */ $version = $function->getAttribute('version', 'v2'); $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); @@ -280,7 +327,6 @@ class Functions extends Action $headers['x-appwrite-user-id'] = $user->getId() ?? ''; $headers['x-appwrite-user-jwt'] = $jwt ?? ''; - /** Create execution or update execution status */ /** Create execution or update execution status */ $execution = $dbForProject->getDocument('executions', $executionId ?? ''); if ($execution->isEmpty()) { From ec930bf125be181e09df4248793ca69f2d91d8a9 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Mon, 1 Apr 2024 17:18:42 +0530 Subject: [PATCH 2/6] Add request headers --- src/Appwrite/Platform/Workers/Functions.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index e7f28a8dcb..8ed69987e5 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -200,6 +200,8 @@ class Functions extends Action * @param string $path * @param string $method * @param Document $user + * @param string|null $jwt + * @param string|null $event * @throws Exception */ private function fail( @@ -209,7 +211,21 @@ class Functions extends Action string $path, string $method, Document $user, + string $jwt = null, + string $event = null, ): void { + $headers['x-appwrite-trigger'] = $trigger; + $headers['x-appwrite-event'] = $event ?? ''; + $headers['x-appwrite-user-id'] = $user->getId() ?? ''; + $headers['x-appwrite-user-jwt'] = $jwt ?? ''; + + $headersFiltered = []; + foreach ($headers as $key => $value) { + if (\in_array(\strtolower($key), FUNCTION_ALLOWLIST_HEADERS_REQUEST)) { + $headersFiltered[] = ['name' => $key, 'value' => $value]; + } + } + $executionId = ID::unique(); $execution = new Document([ '$id' => $executionId, @@ -224,6 +240,7 @@ class Functions extends Action 'responseHeaders' => [], 'requestPath' => $path, 'requestMethod' => $method, + 'requestHeaders' => $headersFiltered, 'errors' => 'Deployment not found. Create deployment before trying to execute a function.', 'logs' => '', 'duration' => 0.0, @@ -293,12 +310,12 @@ class Functions extends Action $deployment = $dbForProject->getDocument('deployments', $deploymentId); if ($deployment->getAttribute('resourceId') !== $functionId) { - $this->fail($dbForProject, $function, $trigger, $path, $method, $user); + $this->fail($dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); return; } if ($deployment->isEmpty()) { - $this->fail($dbForProject, $function, $trigger, $path, $method, $user); + $this->fail($dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); return; } From a3a7763340643f3e9768216d3e966699066442c7 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Mon, 1 Apr 2024 19:07:17 +0530 Subject: [PATCH 3/6] Created failed execution for build errors --- src/Appwrite/Platform/Workers/Functions.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 8ed69987e5..1a86579662 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -195,6 +195,7 @@ class Functions extends Action } /** + * @param string $message * @param Document $function * @param string $trigger * @param string $path @@ -205,6 +206,7 @@ class Functions extends Action * @throws Exception */ private function fail( + string $message, Database $dbForProject, Document $function, string $trigger, @@ -241,7 +243,7 @@ class Functions extends Action 'requestPath' => $path, 'requestMethod' => $method, 'requestHeaders' => $headersFiltered, - 'errors' => 'Deployment not found. Create deployment before trying to execute a function.', + 'errors' => $message, 'logs' => '', 'duration' => 0.0, 'search' => implode(' ', [$function->getId(), $executionId]), @@ -310,23 +312,29 @@ class Functions extends Action $deployment = $dbForProject->getDocument('deployments', $deploymentId); if ($deployment->getAttribute('resourceId') !== $functionId) { - $this->fail($dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); + $errorMessage = 'The execution could not be completed because a corresponding deployment was not found. A function deployment needs to be created before it can be executed. Please create a deployment for your function and try again.'; + $this->fail($errorMessage, $dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); return; } if ($deployment->isEmpty()) { - $this->fail($dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); + $errorMessage = 'The execution could not be completed because a corresponding deployment was not found. A function deployment needs to be created before it can be executed. Please create a deployment for your function and try again.'; + $this->fail($errorMessage, $dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); return; } /** Check if the build exists */ $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); if ($build->isEmpty()) { - throw new Exception('Build not found'); + $errorMessage = 'The execution could not be completed because a corresponding build was not found. A function build needs to be created before it can be executed. Please create a build for your function and try again.'; + $this->fail($errorMessage, $dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); + return; } if ($build->getAttribute('status') !== 'ready') { - throw new Exception('Build not ready'); + $errorMessage = 'The execution could not be completed because the build is not ready. Please wait for the build to complete and try again.'; + $this->fail($errorMessage, $dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); + return; } /** Check if runtime is supported */ From e7e85bfb764d7d47d5858c630a06526a1b062c71 Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Mon, 1 Apr 2024 19:37:51 +0530 Subject: [PATCH 4/6] Update response code --- src/Appwrite/Platform/Workers/Functions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 1a86579662..2ae644a24e 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -238,7 +238,7 @@ class Functions extends Action 'deploymentId' => '', 'trigger' => $trigger, 'status' => 'failed', - 'responseStatusCode' => 400, + 'responseStatusCode' => 0, 'responseHeaders' => [], 'requestPath' => $path, 'requestMethod' => $method, @@ -326,7 +326,7 @@ class Functions extends Action /** Check if the build exists */ $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); if ($build->isEmpty()) { - $errorMessage = 'The execution could not be completed because a corresponding build was not found. A function build needs to be created before it can be executed. Please create a build for your function and try again.'; + $errorMessage = 'The execution could not be completed because a corresponding deployment was not found. A function deployment needs to be created before it can be executed. Please create a deployment for your function and try again.'; $this->fail($errorMessage, $dbForProject, $function, $trigger, $path, $method, $user, $jwt, $event); return; } From 3469ebf7b046724615f7e16687606cd5ccf306cd Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Mon, 1 Apr 2024 23:07:11 +0530 Subject: [PATCH 5/6] Add var_dump to debug flaky test --- tests/e2e/Services/Functions/FunctionsCustomServerTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index e39c6573e4..56e1c24bd3 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -1069,6 +1069,8 @@ class FunctionsCustomServerTest extends Scope 'async' => false ]); + var_dump($execution['body']); + $executionId = $execution['body']['$id'] ?? ''; $output = json_decode($execution['body']['responseBody'], true); From 26db6fa4c51657a312bf181260c6b10e4e25e32b Mon Sep 17 00:00:00 2001 From: Khushboo Verma <43381712+vermakhushboo@users.noreply.github.com> Date: Tue, 2 Apr 2024 17:49:09 +0530 Subject: [PATCH 6/6] Remove var-dump --- tests/e2e/Services/Functions/FunctionsCustomServerTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 56e1c24bd3..e39c6573e4 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -1069,8 +1069,6 @@ class FunctionsCustomServerTest extends Scope 'async' => false ]); - var_dump($execution['body']); - $executionId = $execution['body']['$id'] ?? ''; $output = json_decode($execution['body']['responseBody'], true);