feat: sync master and fix tests
This commit is contained in:
parent
c595f4eea9
commit
f65b3e0c5b
|
@ -314,7 +314,7 @@ function createRuntimeServer(string $functionId, string $projectId, string $depl
|
|||
|
||||
Console::success('Runtime Server created in ' . ($executionEnd - $executionStart) . ' seconds');
|
||||
} else {
|
||||
Console::info('Runtime server is ready to run');
|
||||
Console::success('Runtime server is ready to run');
|
||||
}
|
||||
} catch (\Throwable $th) {
|
||||
var_dump($th->getTraceAsString());
|
||||
|
@ -943,6 +943,7 @@ App::post('/v1/functions/:functionId/executions')
|
|||
);
|
||||
|
||||
App::delete('/v1/functions/:functionId')
|
||||
->desc('Delete a function')
|
||||
->param('functionId', '', new UID())
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
@ -1005,7 +1006,7 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/runtime')
|
|||
->param('deploymentId', '', new UID(), 'Deployment unique ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('projectID')
|
||||
->inject('projectId')
|
||||
->action(function (string $functionId, string $deploymentId, Response $response, Database $dbForProject, string $projectID) use ($runtimes) {
|
||||
// Get function document
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
@ -1032,6 +1033,7 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/runtime')
|
|||
});
|
||||
|
||||
App::delete('/v1/deployments/:deploymentId')
|
||||
->desc('Delete a deployment')
|
||||
->param('deploymentId', '', new UID(), 'Deployment unique ID.')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
|
@ -1077,41 +1079,81 @@ App::delete('/v1/deployments/:deploymentId')
|
|||
return $response->json(['success' => true]);
|
||||
});
|
||||
|
||||
App::post('/v1/builds/:buildId')
|
||||
App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId')
|
||||
->desc("Create a new build")
|
||||
->param('functionId', '', new UID(), 'Function unique ID.', false)
|
||||
->param('deploymentId', '', new UID(), 'Deployment unique ID.', false)
|
||||
->param('buildId', '', new UID(), 'Build unique ID.', false)
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('projectID')
|
||||
->action(function (string $buildId, Response $response, Database $dbForProject, string $projectID) {
|
||||
try {
|
||||
// Get build document
|
||||
->inject('projectId')
|
||||
->action(function (string $functionId, string $deploymentId, string $buildId, Response $response, Database $dbForProject, string $projectId) {
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404);
|
||||
}
|
||||
|
||||
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
|
||||
if ($deployment->isEmpty()) {
|
||||
throw new Exception('Deployment not found', 404);
|
||||
}
|
||||
|
||||
$build = $dbForProject->getDocument('builds', $buildId);
|
||||
if ($build->isEmpty()) {
|
||||
throw new Exception('Build not found', 404);
|
||||
}
|
||||
|
||||
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 ($functionId, $deploymentId, $buildId, $projectId, $dbForProject, $function, $deployment) {
|
||||
Console::info('Starting build for deployment ' . $deployment['$id']);
|
||||
runBuildStage($buildId, $projectId);
|
||||
|
||||
// Update the schedule
|
||||
$schedule = $function->getAttribute('schedule', '');
|
||||
$cron = (empty($function->getAttribute('deployment')) && !empty($schedule)) ? new CronExpression($schedule) : null;
|
||||
$next = (empty($function->getAttribute('deployment')) && !empty($schedule)) ? $cron->getNextRunDate()->format('U') : 0;
|
||||
|
||||
// Grab build
|
||||
$build = $dbForProject->getDocument('builds', $buildId);
|
||||
|
||||
// Check if build exists
|
||||
if ($build->isEmpty()) {
|
||||
throw new Exception('Build not found', 404);
|
||||
// If the build failed, it won't be possible to deploy
|
||||
if ($build->getAttribute('status') !== 'ready') {
|
||||
throw new Exception('Build failed', 500);
|
||||
}
|
||||
|
||||
// Check if build is already running
|
||||
if ($build->getAttribute('status') === 'running') {
|
||||
throw new Exception('Build is already running', 409);
|
||||
if ($deployment->getAttribute('deploy') === true) {
|
||||
// Update the function document setting the deployment as the active one
|
||||
$function
|
||||
->setAttribute('deployment', $deployment->getId())
|
||||
->setAttribute('scheduleNext', (int)$next);
|
||||
|
||||
$function = $dbForProject->updateDocument('functions', $functionId, $function);
|
||||
}
|
||||
|
||||
// Check if build is already finished
|
||||
if ($build->getAttribute('status') === 'finished') {
|
||||
throw new Exception('Build is already finished', 409);
|
||||
// Deploy Runtime Server
|
||||
try {
|
||||
Console::info("[ INFO ] Creating runtime server");
|
||||
createRuntimeServer($functionId, $projectId, $deploymentId, $dbForProject);
|
||||
} catch (\Throwable $th) {
|
||||
Console::error($th->getMessage());
|
||||
$deployment->setAttribute('status', 'failed');
|
||||
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
|
||||
throw $th;
|
||||
}
|
||||
|
||||
runBuildStage($buildId, $projectID, $dbForProject);
|
||||
});
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->send();
|
||||
} catch (Exception $e) {
|
||||
// TODO : @matej,why do we need to log here ? There is a global error handler that logs errors
|
||||
logError($e, "buildEndpoint");
|
||||
throw $e;
|
||||
}
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_CREATED)
|
||||
->send();
|
||||
});
|
||||
|
||||
App::setMode(App::MODE_TYPE_PRODUCTION); // Define Mode
|
||||
|
@ -1276,7 +1318,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo
|
|||
);
|
||||
}, ['error', 'utopia', 'request', 'response']);
|
||||
|
||||
App::setResource('projectID', function () use ($projectId) {
|
||||
App::setResource('projectId', function () use ($projectId) {
|
||||
return $projectId;
|
||||
});
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ use Utopia\Logger\Log\User;
|
|||
$http = new Server("0.0.0.0", App::getEnv('PORT', 80));
|
||||
|
||||
$http->set([
|
||||
'worker_num' => 1,
|
||||
'worker_num' => 4,
|
||||
'reactor_num' => 6
|
||||
]);
|
||||
|
||||
|
|
|
@ -43,8 +43,10 @@ class BuildsV1 extends Worker
|
|||
|
||||
case BUILD_TYPE_RETRY:
|
||||
$buildId = $this->args['buildId'] ?? '';
|
||||
$functionId = $this->args['functionId'] ?? '';
|
||||
$deploymentId = $this->args['deploymentId'] ?? '';
|
||||
Console::info("[ INFO ] Retrying build for id: $buildId");
|
||||
$this->triggerBuild($projectId, $buildId);
|
||||
$this->createBuild($projectId, $functionId, $deploymentId, $buildId);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -53,40 +55,11 @@ class BuildsV1 extends Worker
|
|||
}
|
||||
}
|
||||
|
||||
protected function triggerBuild(string $projectId, string $buildId)
|
||||
protected function createBuild(string $projectId, string $functionId, string $deploymentId, string $buildId)
|
||||
{
|
||||
// TODO: What is a reasonable time to wait for a build to complete?
|
||||
$ch = \curl_init();
|
||||
\curl_setopt($ch, CURLOPT_URL, "http://appwrite-executor/v1/builds/$buildId");
|
||||
\curl_setopt($ch, CURLOPT_POST, true);
|
||||
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
\curl_setopt($ch, CURLOPT_TIMEOUT, 900);
|
||||
\curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
\curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'x-appwrite-project: '.$projectId,
|
||||
'x-appwrite-executor-key: '. App::getEnv('_APP_EXECUTOR_SECRET', '')
|
||||
]);
|
||||
|
||||
$response = \curl_exec($ch);
|
||||
$responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
$error = \curl_error($ch);
|
||||
if (!empty($error)) {
|
||||
throw new \Exception($error);
|
||||
}
|
||||
|
||||
\curl_close($ch);
|
||||
|
||||
if ($responseStatus >= 400) {
|
||||
throw new \Exception("Build failed with status code: $responseStatus");
|
||||
}
|
||||
}
|
||||
|
||||
protected function triggerCreateRuntimeServer(string $projectId, string $functionId, string $deploymentId)
|
||||
{
|
||||
$ch = \curl_init();
|
||||
\curl_setopt($ch, CURLOPT_URL, "http://appwrite-executor/v1/functions/$functionId/deployments/$deploymentId/runtime");
|
||||
\curl_setopt($ch, CURLOPT_URL, "http://appwrite-executor/v1/functions/$functionId/deployments/$deploymentId/builds/$buildId");
|
||||
\curl_setopt($ch, CURLOPT_POST, true);
|
||||
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
\curl_setopt($ch, CURLOPT_TIMEOUT, 900);
|
||||
|
@ -117,7 +90,6 @@ class BuildsV1 extends Worker
|
|||
$dbForProject = $this->getProjectDB($projectId);
|
||||
|
||||
$function = $dbForProject->getDocument('functions', $functionId);
|
||||
|
||||
if ($function->isEmpty()) {
|
||||
throw new Exception('Function not found', 404);
|
||||
}
|
||||
|
@ -142,7 +114,6 @@ class BuildsV1 extends Worker
|
|||
try {
|
||||
$buildId = $dbForProject->getId();
|
||||
// TODO : There is no way to associate a build with a deployment. So we need to add a deploymentId attribute to the build document
|
||||
// TODO : What should be the read and write permissions for a build ?
|
||||
$dbForProject->createDocument('builds', new Document([
|
||||
'$id' => $buildId,
|
||||
'$read' => [],
|
||||
|
@ -170,11 +141,11 @@ class BuildsV1 extends Worker
|
|||
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
|
||||
|
||||
} catch (\Throwable $th) {
|
||||
Console::error($th->getMessage());
|
||||
$deployment->setAttribute('status', 'failed');
|
||||
$deployment->setAttribute('buildId', '');
|
||||
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
|
||||
return;
|
||||
Console::error($th->getMessage());
|
||||
throw $th;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,50 +154,15 @@ class BuildsV1 extends Worker
|
|||
Console::info("[ INFO ] Creating build with id: $buildId");
|
||||
$deployment->setAttribute('status', 'building');
|
||||
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
|
||||
$this->triggerBuild($projectId, $buildId);
|
||||
$this->createBuild($projectId, $functionId, $deploymentId, $buildId);
|
||||
} catch (\Throwable $th) {
|
||||
Console::error($th->getMessage());
|
||||
$deployment->setAttribute('status', 'failed');
|
||||
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
|
||||
return;
|
||||
}
|
||||
|
||||
Console::success("[ SUCCESS ] Build id: $buildId completed");
|
||||
|
||||
// Update the schedule
|
||||
$schedule = $function->getAttribute('schedule', '');
|
||||
$cron = (empty($function->getAttribute('deployment')) && !empty($schedule)) ? new CronExpression($schedule) : null;
|
||||
$next = (empty($function->getAttribute('deployment')) && !empty($schedule)) ? $cron->getNextRunDate()->format('U') : 0;
|
||||
|
||||
// Grab build
|
||||
$build = $dbForProject->getDocument('builds', $buildId);
|
||||
|
||||
// If the build failed, it won't be possible to deploy
|
||||
if ($build->getAttribute('status') !== 'ready') {
|
||||
throw new Exception('Build failed', 500);
|
||||
}
|
||||
|
||||
if ($deployment->getAttribute('deploy') === true) {
|
||||
// Update the function document setting the deployment as the active one
|
||||
$function
|
||||
->setAttribute('deployment', $deployment->getId())
|
||||
->setAttribute('scheduleNext', (int)$next);
|
||||
|
||||
$function = $dbForProject->updateDocument('functions', $functionId, $function);
|
||||
}
|
||||
|
||||
// Deploy Runtime Server
|
||||
try {
|
||||
Console::info("[ INFO ] Creating runtime server");
|
||||
$this->triggerCreateRuntimeServer($projectId, $functionId, $deploymentId, $dbForProject);
|
||||
} catch (\Throwable $th) {
|
||||
Console::error($th->getMessage());
|
||||
$deployment->setAttribute('status', 'failed');
|
||||
$deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment);
|
||||
return;
|
||||
throw $th;
|
||||
}
|
||||
|
||||
Console::success("[ SUCCESS ] Runtime Server created");
|
||||
Console::success("[ SUCCESS ] Build id: $buildId started");
|
||||
}
|
||||
|
||||
public function shutdown(): void {}
|
||||
|
|
|
@ -378,8 +378,14 @@ services:
|
|||
|
||||
appwrite-executor:
|
||||
container_name: appwrite-executor
|
||||
entrypoint: executor
|
||||
entrypoint:
|
||||
- php
|
||||
- -e
|
||||
- /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:
|
||||
|
|
Loading…
Reference in a new issue