From e1457618002e69258b225276d7544f67486d1eb9 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 15 Mar 2022 01:02:24 +0400 Subject: [PATCH 01/11] feat: use build timeout when building runtime --- app/executor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/executor.php b/app/executor.php index 1fa32599ab..528591e2c1 100644 --- a/app/executor.php +++ b/app/executor.php @@ -247,7 +247,7 @@ App::post('/v1/runtimes') command: $commands, stdout: $stdout, stderr: $stderr, - timeout: App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900) + timeout: App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900) ); if (!$status) { From d17e252f931c115a69088f13e43c43a1281b7acd Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 15 Mar 2022 15:56:00 +0400 Subject: [PATCH 02/11] feat: handle errros better in the executor --- app/executor.php | 57 +++++++++++++++++++----------------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/app/executor.php b/app/executor.php index 528591e2c1..aca46c17a1 100644 --- a/app/executor.php +++ b/app/executor.php @@ -455,45 +455,32 @@ App::post('/v1/execution') \curl_close($ch); - // If timeout error - if (in_array($errNo, [CURLE_OPERATION_TIMEDOUT, 110])) { - $statusCode = 124; + switch (true) { + /** No Error. */ + case $errNo === 0: break; + /** Connection Refused. Runtime not ready for requests yet . 111 is the swoole error code for Connection Refused */ + case $errNo === 111: + throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 406); + /** Every other CURL error */ + default: + throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 500); } - - // 110 is the Swoole error code for timeout, see: https://www.swoole.co.uk/docs/swoole-error-code - if ($errNo !== 0 && $errNo !== CURLE_COULDNT_CONNECT && $errNo !== CURLE_OPERATION_TIMEDOUT && $errNo !== 110) { - throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 406); + + switch (true) { + case $statusCode >= 500: + $stderr = $executorResponse ?? 'Internal Runtime error.'; + break; + case $statusCode >= 200: + $stdout = $executorResponse; + break; + default: + $stderr = $executorResponse ?? 'Execution failed.'; + break; } - - $executionData = []; - - if (!empty($executorResponse)) { - $executionData = json_decode($executorResponse, true); - } - - if (isset($executionData['code'])) { - $statusCode = $executionData['code']; - } - - if ($statusCode === 500) { - if (isset($executionData['message'])) { - $stderr = $executionData['message']; - } else { - $stderr = 'Internal Runtime error'; - } - } else if ($statusCode === 124) { - $stderr = 'Execution timed out.'; - } else if ($statusCode === 0) { - $stderr = 'Execution failed.'; - } else if ($statusCode >= 200 && $statusCode < 300) { - $stdout = $executorResponse; - } else { - $stderr = 'Execution failed.'; - } - + $executionEnd = \microtime(true); $executionTime = ($executionEnd - $executionStart); - $functionStatus = ($statusCode >= 200 && $statusCode < 300) ? 'completed' : 'failed'; + $functionStatus = ($statusCode >= 500) ? 'failed' : 'completed'; Console::success('Function executed in ' . $executionTime . ' seconds, status: ' . $functionStatus); From 1728833307f71d0eced06096305f597f8a7a04a1 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 15 Mar 2022 16:04:43 +0400 Subject: [PATCH 03/11] feat: update error message --- app/executor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/executor.php b/app/executor.php index aca46c17a1..7948a73feb 100644 --- a/app/executor.php +++ b/app/executor.php @@ -458,10 +458,10 @@ App::post('/v1/execution') switch (true) { /** No Error. */ case $errNo === 0: break; - /** Connection Refused. Runtime not ready for requests yet . 111 is the swoole error code for Connection Refused */ + /** Runtime not ready for requests yet. 111 is the swoole error code for Connection Refused - see https://openswoole.com/docs/swoole-error-code */ case $errNo === 111: throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 406); - /** Every other CURL error */ + /** Any other CURL error */ default: throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 500); } From ee056e582f274403dddddb2518d030de79473eab Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 15 Mar 2022 17:06:05 +0400 Subject: [PATCH 04/11] feat: function execution time for failed executions --- app/controllers/api/functions.php | 3 +++ app/executor.php | 2 +- app/workers/functions.php | 3 +++ tests/e2e/Services/Functions/FunctionsCustomServerTest.php | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index d491b7d75b..8293da16ba 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -960,6 +960,9 @@ App::post('/v1/functions/:functionId/executions') $execution->setAttribute('stderr', $executionResponse['stderr']); $execution->setAttribute('time', $executionResponse['time']); } catch (\Throwable $th) { + $endtime = \time(); + $time = $endtime - $execution->getAttribute('dateCreated'); + $execution->setAttribute('time', $time); $execution->setAttribute('status', 'failed'); $execution->setAttribute('statusCode', $th->getCode()); $execution->setAttribute('stderr', $th->getMessage()); diff --git a/app/executor.php b/app/executor.php index 7948a73feb..d96e86f7d9 100644 --- a/app/executor.php +++ b/app/executor.php @@ -470,7 +470,7 @@ App::post('/v1/execution') case $statusCode >= 500: $stderr = $executorResponse ?? 'Internal Runtime error.'; break; - case $statusCode >= 200: + case $statusCode >= 100: $stdout = $executorResponse; break; default: diff --git a/app/workers/functions.php b/app/workers/functions.php index 2d4cdb2e54..41e685a4dd 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -307,6 +307,9 @@ class FunctionsV1 extends Worker $execution->setAttribute('stderr', $executionResponse['stderr']); $execution->setAttribute('time', $executionResponse['time']); } catch (\Throwable $th) { + $endtime = \time(); + $time = $endtime - $execution->getAttribute('dateCreated'); + $execution->setAttribute('time', $time); $execution->setAttribute('status', 'failed'); $execution->setAttribute('statusCode', $th->getCode()); $execution->setAttribute('stderr', $th->getMessage()); diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index e26f93ad34..274a9f07b1 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -761,7 +761,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['$id'], $executionId); $this->assertEquals($executions['body']['executions'][0]['trigger'], 'http'); $this->assertEquals($executions['body']['executions'][0]['status'], 'failed'); - $this->assertEquals($executions['body']['executions'][0]['statusCode'], 124); + $this->assertEquals($executions['body']['executions'][0]['statusCode'], 500); $this->assertGreaterThan(2, $executions['body']['executions'][0]['time']); $this->assertLessThan(3, $executions['body']['executions'][0]['time']); $this->assertEquals($executions['body']['executions'][0]['stdout'], ''); From 13b28e0051f73e540de55770a4ebf4d1ad44e1c2 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 15 Mar 2022 18:51:32 +0400 Subject: [PATCH 05/11] feat: update test message --- app/controllers/api/functions.php | 2 +- app/executor.php | 3 ++- app/workers/functions.php | 3 ++- src/Executor/Executor.php | 6 ++++-- tests/e2e/Services/Functions/FunctionsCustomServerTest.php | 4 ++-- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 8293da16ba..5b076b1c59 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -960,7 +960,7 @@ App::post('/v1/functions/:functionId/executions') $execution->setAttribute('stderr', $executionResponse['stderr']); $execution->setAttribute('time', $executionResponse['time']); } catch (\Throwable $th) { - $endtime = \time(); + $endtime = \microtime(true); $time = $endtime - $execution->getAttribute('dateCreated'); $execution->setAttribute('time', $time); $execution->setAttribute('status', 'failed'); diff --git a/app/executor.php b/app/executor.php index d96e86f7d9..50133225ca 100644 --- a/app/executor.php +++ b/app/executor.php @@ -457,7 +457,8 @@ App::post('/v1/execution') switch (true) { /** No Error. */ - case $errNo === 0: break; + case $errNo === 0: + break; /** Runtime not ready for requests yet. 111 is the swoole error code for Connection Refused - see https://openswoole.com/docs/swoole-error-code */ case $errNo === 111: throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 406); diff --git a/app/workers/functions.php b/app/workers/functions.php index 41e685a4dd..6ab1289a20 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -287,6 +287,7 @@ class FunctionsV1 extends Worker $vars = \array_merge($function->getAttribute('vars', []), $vars); /** Execute function */ + $startTime = microtime(true); try { $executionResponse = $this->executor->createExecution( projectId: $projectId, @@ -307,7 +308,7 @@ class FunctionsV1 extends Worker $execution->setAttribute('stderr', $executionResponse['stderr']); $execution->setAttribute('time', $executionResponse['time']); } catch (\Throwable $th) { - $endtime = \time(); + $endtime = \microtime(true); $time = $endtime - $execution->getAttribute('dateCreated'); $execution->setAttribute('time', $time); $execution->setAttribute('status', 'failed'); diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 1a96b3561b..213db074c1 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -161,12 +161,14 @@ class Executor 'timeout' => $timeout, ]; - /* Add 2 seconds as a buffer to the actual timeout value since there can be a slight variance*/ - $requestTimeout = $timeout + 2; + /* Add 1 second as a buffer to the actual timeout value since there can be a slight variance*/ + $requestTimeout = $timeout + 1; $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $requestTimeout); $status = $response['headers']['status-code']; + var_dump($response); + var_dump($status); for ($attempts = 0; $attempts < 10; $attempts++) { try { switch (true) { diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 274a9f07b1..f2b29d6317 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -763,9 +763,9 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['status'], 'failed'); $this->assertEquals($executions['body']['executions'][0]['statusCode'], 500); $this->assertGreaterThan(2, $executions['body']['executions'][0]['time']); - $this->assertLessThan(3, $executions['body']['executions'][0]['time']); + $this->assertLessThan(6, $executions['body']['executions'][0]['time']); $this->assertEquals($executions['body']['executions'][0]['stdout'], ''); - $this->assertEquals($executions['body']['executions'][0]['stderr'], 'Execution timed out.'); + $this->assertEquals($executions['body']['executions'][0]['stderr'], 'An internal curl error has occurred within the executor! Error Msg: Operation timed out'); // Cleanup : Delete function $response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [ From 7a2614ed6d6587ae26871dc5c5a5a5d0f93dc34b Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 15 Mar 2022 18:53:20 +0400 Subject: [PATCH 06/11] feat: update test message --- app/workers/functions.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/workers/functions.php b/app/workers/functions.php index 6ab1289a20..7033e5aa5c 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -287,7 +287,6 @@ class FunctionsV1 extends Worker $vars = \array_merge($function->getAttribute('vars', []), $vars); /** Execute function */ - $startTime = microtime(true); try { $executionResponse = $this->executor->createExecution( projectId: $projectId, From 91bd8983924145f0b96b7ec24434b5dd8c2be78f Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 15 Mar 2022 18:53:48 +0400 Subject: [PATCH 07/11] feat: remove var_dump --- src/Executor/Executor.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 213db074c1..9ba9675f30 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -167,8 +167,6 @@ class Executor $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $requestTimeout); $status = $response['headers']['status-code']; - var_dump($response); - var_dump($status); for ($attempts = 0; $attempts < 10; $attempts++) { try { switch (true) { From 1fd053a8b7f21d212b9abf8826ae02364b7891f4 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 15 Mar 2022 18:56:12 +0400 Subject: [PATCH 08/11] feat: remove var_dump --- src/Executor/Executor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 9ba9675f30..1a96b3561b 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -161,8 +161,8 @@ class Executor 'timeout' => $timeout, ]; - /* Add 1 second as a buffer to the actual timeout value since there can be a slight variance*/ - $requestTimeout = $timeout + 1; + /* Add 2 seconds as a buffer to the actual timeout value since there can be a slight variance*/ + $requestTimeout = $timeout + 2; $response = $this->call(self::METHOD_POST, $route, $headers, $params, true, $requestTimeout); $status = $response['headers']['status-code']; From f45919aef4a2c934b95e0fd36582b43329453659 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 12 May 2022 19:37:15 +0200 Subject: [PATCH 09/11] tests: fix stdout --- tests/e2e/Services/Functions/FunctionsCustomServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 02a7ba0b23..9b2f563ac9 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -764,7 +764,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals($executions['body']['executions'][0]['statusCode'], 500); $this->assertGreaterThan(2, $executions['body']['executions'][0]['time']); $this->assertLessThan(6, $executions['body']['executions'][0]['time']); - $this->assertEquals($executions['body']['executions'][0]['stdout'], ''); + $this->assertEquals($executions['body']['executions'][0]['response'], ''); $this->assertEquals($executions['body']['executions'][0]['stderr'], 'An internal curl error has occurred within the executor! Error Msg: Operation timed out'); // Cleanup : Delete function From 684beb3cb5c3f19b5cecba1b6bde34eb76e47637 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 12 May 2022 19:55:48 +0200 Subject: [PATCH 10/11] tests: fix timeout --- tests/e2e/Services/Functions/FunctionsCustomServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 9b2f563ac9..aa87081541 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -747,7 +747,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(201, $execution['headers']['status-code']); - sleep(5); + sleep(10); $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([ 'content-type' => 'application/json', From 53f2b5a57ae765b6918b16da241055a05a623ae5 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Thu, 12 May 2022 20:05:11 +0200 Subject: [PATCH 11/11] fix: reconnect behaviour --- app/tasks/maintenance.php | 5 +++++ src/Appwrite/Resque/Worker.php | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/tasks/maintenance.php b/app/tasks/maintenance.php index 3bb528c4d9..6ba744fde0 100644 --- a/app/tasks/maintenance.php +++ b/app/tasks/maintenance.php @@ -27,6 +27,11 @@ function getConsoleDB(): Database $database = new Database(new MariaDB($register->get('db')), $cache); $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); $database->setNamespace('_console'); // Main DB + + if (!$database->exists($database->getDefaultDatabase(), '_metadata')) { + throw new \Exception('Console project not ready'); + } + break; // leave loop if successful } catch (\Exception $e) { Console::warning("Database not ready. Retrying connection ({$attempts})..."); diff --git a/src/Appwrite/Resque/Worker.php b/src/Appwrite/Resque/Worker.php index 9682688736..88489b5412 100644 --- a/src/Appwrite/Resque/Worker.php +++ b/src/Appwrite/Resque/Worker.php @@ -209,7 +209,7 @@ abstract class Worker throw new \Exception("Project does not exist: {$projectId}"); } - if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), 'realtime')) { + if ($type === self::DATABASE_CONSOLE && !$database->exists($database->getDefaultDatabase(), '_metadata')) { throw new \Exception('Console project not ready'); }