1
0
Fork 0
mirror of synced 2024-06-29 19:50:26 +12:00

Merge pull request #2706 from appwrite/feat-add-deletes-worker

Feat add deletes worker
This commit is contained in:
Christy Jacob 2022-02-15 15:01:19 +04:00 committed by GitHub
commit a84f0ebbcb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 294 additions and 207 deletions

View file

@ -2158,9 +2158,9 @@ $collections = [
],
'indexes' => [
[
'$id' => '_key_status',
'$id' => '_key_deployment',
'type' => Database::INDEX_KEY,
'attributes' => ['status'],
'attributes' => ['deploymentId'],
'lengths' => [Database::LENGTH_KEY],
'orders' => [Database::ORDER_ASC],
]

View file

@ -423,44 +423,13 @@ App::delete('/v1/functions/:functionId')
->inject('response')
->inject('dbForProject')
->inject('deletes')
->inject('project')
->action(function ($functionId, $response, $dbForProject, $deletes, $project) {
->action(function ($functionId, $response, $dbForProject, $deletes) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $deletes */
/** @var Utopia\Database\Document $project */
$function = $dbForProject->getDocument('functions', $functionId);
// Request executor to delete deployment containers
$ch = \curl_init();
\curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
\curl_setopt($ch, CURLOPT_URL, "http://appwrite-executor/v1/functions/$functionId");
\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: '.$project->getId(),
'x-appwrite-executor-key: '. App::getEnv('_APP_EXECUTOR_SECRET', '')
]);
$executorResponse = \curl_exec($ch);
$error = \curl_error($ch);
if (!empty($error)) {
throw new Exception('Executor Cleanup Error: ' . $error, 500);
}
// Check status code
$statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (200 !== $statusCode) {
throw new Exception('Executor error: ' . $executorResponse, $statusCode);
}
\curl_close($ch);
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
}
@ -713,64 +682,29 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId')
->inject('response')
->inject('dbForProject')
->inject('usage')
->inject('project')
->action(function ($functionId, $deploymentId, $response, $dbForProject, $usage, $project) {
->inject('deletes')
->action(function ($functionId, $deploymentId, $response, $dbForProject, $usage, $deletes) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForProject */
/** @var Appwrite\Event\Event $usage */
/** @var Utopia\Database\Document $project */
/** @var Appwrite\Event\Event $deletes */
$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);
}
if ($deployment->getAttribute('resourceId') !== $function->getId()) {
throw new Exception('Deployment not found', 404);
}
if ($deployment->isEmpty()) {
throw new Exception('deployment not found', 404);
}
// Request executor to delete deployment containers
$ch = \curl_init();
\curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
\curl_setopt($ch, CURLOPT_URL, "http://appwrite-executor/v1/deployments/$deploymentId");
\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: '.$project->getId(),
'x-appwrite-executor-key: '. App::getEnv('_APP_EXECUTOR_SECRET', '')
]);
$executorResponse = \curl_exec($ch);
$error = \curl_error($ch);
if (!empty($error)) {
throw new Exception('Executor Cleanup error: ' . $error, 500);
}
// Check status code
$statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (200 !== $statusCode) {
throw new Exception('Executor error: ' . $executorResponse, $statusCode);
}
\curl_close($ch);
$device = Storage::getDevice('functions');
if ($device->delete($deployment->getAttribute('path', ''))) {
if (!$dbForProject->deleteDocument('deployments', $deployment->getId())) {
throw new Exception('Failed to remove deployment from DB', 500);
}
if (!$dbForProject->deleteDocument('deployments', $deployment->getId())) {
throw new Exception('Failed to remove deployment from DB', 500);
}
if($function->getAttribute('deployment') === $deployment->getId()) { // Reset function deployment
@ -783,6 +717,11 @@ App::delete('/v1/functions/:functionId/deployments/:deploymentId')
->setParam('storage', $deployment->getAttribute('size', 0) * -1)
;
$deletes
->setParam('type', DELETE_TYPE_DOCUMENT)
->setParam('document', $deployment)
;
$response->noContent();
});

View file

@ -408,7 +408,7 @@ function execute(string $trigger, string $projectId, string $executionId, string
$buildId = $database->getId();
$database->createDocument('builds', new Document([
'$id' => $buildId,
'$read' => ($userId !== '') ? ['user:' . $userId] : [],
'$read' => [],
'$write' => [],
'startTime' => time(),
'deploymentId' => $deployment->getId(),
@ -685,9 +685,7 @@ function runBuildStage(string $buildId, string $deploymentId, string $projectID)
// Update deployment Status
$build->setAttribute('status', 'building');
$deployment->setAttribute('status', 'building');
$database->updateDocument('builds', $buildId, $build);
$database->updateDocument('deployments', $deploymentId, $deployment);
// Check if runtime is active
$runtime = $runtimes[$build->getAttribute('runtime', '')] ?? null;
@ -748,6 +746,7 @@ function runBuildStage(string $buildId, string $deploymentId, string $projectID)
}
$vars = $resource->getAttribute('vars', []);
$vars['ENTRYPOINT_NAME'] = $resource->getAttribute('entrypoint', '');
$orchestration
->setCpus(App::getEnv('_APP_FUNCTIONS_CPUS', 0))
@ -903,14 +902,11 @@ function runBuildStage(string $buildId, string $deploymentId, string $projectID)
->setAttribute('stdout', \utf8_encode(\mb_substr($buildStdout, -4096)))
->setAttribute('stderr', \utf8_encode(\mb_substr($e->getMessage(), -4096)))
->setAttribute('startTime', $buildStart)
->setAttribute('endTime', \microtime(true))
->setAttribute('duration', \microtime(true) - $buildStart);
->setAttribute('endTime', \time())
->setAttribute('duration', \time() - $buildStart);
$build = $database->updateDocument('builds', $buildId, $build);
$deployment->setAttribute('status', 'failed');
$database->updateDocument('deployments', $deploymentId, $deployment);
// also remove the container if it exists
if (isset($id)) {
$orchestration->remove($id, true);
@ -955,58 +951,63 @@ App::post('/v1/functions/:functionId/executions')
App::delete('/v1/functions/:functionId')
->desc('Delete a function')
->param('functionId', '', new UID(), 'The FunctionID to delete')
->param('functionId', '', new UID())
->inject('projectId')
->inject('response')
->inject('dbForProject')
->action(
function (string $functionId, Response $response, Database $dbForProject) use ($orchestrationPool) {
try {
/** @var Orchestration $orchestration */
$orchestration = $orchestrationPool->get();
// Get function document
$function = $dbForProject->getDocument('functions', $functionId);
function (string $functionId, string $projectId, Response $response, Database $dbForProject) use ($orchestrationPool) {
// Check if function exists
if ($function->isEmpty()) {
throw new Exception('Function not found', 404);
}
$results = $dbForProject->find('deployments', [new Query('functionId', Query::TYPE_EQUAL, [$functionId])], 999);
// If amount is 0 then we simply return true
if (count($results) === 0) {
$response
->setStatusCode(Response::STATUS_CODE_OK)
->send();
}
// Delete the containers of all deployments
foreach ($results as $deployment) {
// 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']);
}
}
$orchestration->remove('appwrite-function-' . $deployment['$id'], true);
Console::info('Removed container for deployment ' . $deployment['$id']);
}
$results = $dbForProject->find('deployments', [new Query('resourceId', Query::TYPE_EQUAL, [$functionId])], 999);
// If amount is 0 then we simply return true
if (count($results) === 0) {
$response
->setStatusCode(Response::STATUS_CODE_OK)
->send();
} catch (Throwable $th) {
$orchestrationPool->put($orchestration);
throw $th;
} finally {
$orchestrationPool->put($orchestration);
}
Console::info('Deleting function: ' . $functionId);
// Delete the containers of all deployments
global $register;
foreach ($results as $deployment) {
go(function () use ($orchestrationPool, $deployment, $register, $projectId) {
$db = $register->get('dbPool')->get();
$redis = $register->get('redisPool')->get();
$cache = new Cache(new RedisCache($redis));
$dbForProject = new Database(new MariaDB($db), $cache);
$dbForProject->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$dbForProject->setNamespace('_project_' . $projectId);
try {
$orchestration = $orchestrationPool->get();
// Remove the container of the deployment
$orchestration->remove('appwrite-function-' . $deployment['$id'], true);
Console::success('Removed container for deployment: ' . $deployment['$id']);
$builds = $dbForProject->find('builds', [
new Query('deploymentId', Query::TYPE_EQUAL, [$deployment['$id']]),
new Query('status', Query::TYPE_EQUAL, ['building'])
], 999);
// Remove all the build containers
foreach ($builds as $build) {
$orchestration->remove('build-stage-' . $build['$id'], true);
Console::success("Removed build contanier: $build for deployment: " . $deployment['$id']);
}
} catch (\Throwable $th) {
Console::error($th->getMessage());
} finally {
$orchestrationPool->put($orchestration);
$register->get('dbPool')->put($db);
$register->get('redisPool')->put($redis);
}
});
}
$response
->setStatusCode(Response::STATUS_CODE_OK)
->send();
}
);
@ -1045,40 +1046,43 @@ 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('projectId')
->inject('response')
->inject('dbForProject')
->action(function (string $deploymentId, Response $response, Database $dbForProject) use ($orchestrationPool) {
try {
/** @var Orchestration $orchestration */
$orchestration = $orchestrationPool->get();
// Get deployment document
$deployment = $dbForProject->getDocument('deployments', $deploymentId);
->action(function (string $deploymentId, string $projectId, Response $response) use ($orchestrationPool) {
Console::info('Deleting deployment: ' . $deploymentId);
global $register;
go(function () use ($projectId, $orchestrationPool, $register, $deploymentId) {
try {
$orchestration = $orchestrationPool->get();
// Remove the container of the deployment
$orchestration->remove('appwrite-function-' . $deploymentId , true);
Console::success('Removed container for deployment: ' . $deploymentId);
// Check if deployment exists
if ($deployment->isEmpty()) {
throw new Exception('Deployment not found', 404);
}
$db = $register->get('dbPool')->get();
$redis = $register->get('redisPool')->get();
$cache = new Cache(new RedisCache($redis));
$dbForProject = new Database(new MariaDB($db), $cache);
$dbForProject->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
$dbForProject->setNamespace('_project_' . $projectId);
// Remove any ongoing builds
if ($deployment->getAttribute('buildId')) {
$build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId'));
$builds = $dbForProject->find('builds', [
new Query('deploymentId', Query::TYPE_EQUAL, [$deploymentId]),
new Query('status', Query::TYPE_EQUAL, ['building'])
], 999);
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 all the build containers
foreach ($builds as $build) {
$orchestration->remove('build-stage-' . $build['$id'], true);
Console::success("Removed build container: $build for deployment: " . $deploymentId);
}
} catch (\Throwable $th) {
Console::error($th->getMessage());
} finally {
$orchestrationPool->put($orchestration);
$register->get('dbPool')->put($db);
$register->get('redisPool')->put($redis);
}
// 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);
});
$response
->setStatusCode(Response::STATUS_CODE_OK)
@ -1147,12 +1151,10 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/builds/:buildId')
// Deploy Runtime Server
try {
Console::info("[ INFO ] Creating runtime server");
Console::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;
}
});

View file

@ -100,6 +100,7 @@ const DELETE_TYPE_DOCUMENT = 'document';
const DELETE_TYPE_COLLECTIONS = 'collections';
const DELETE_TYPE_PROJECTS = 'projects';
const DELETE_TYPE_FUNCTIONS = 'functions';
const DELETE_TYPE_DEPLOYMENTS = 'deployments';
const DELETE_TYPE_USERS = 'users';
const DELETE_TYPE_TEAMS= 'teams';
const DELETE_TYPE_EXECUTIONS = 'executions';

View file

@ -37,7 +37,7 @@ class BuildsV1 extends Worker
case BUILD_TYPE_DEPLOYMENT:
$functionId = $this->args['functionId'] ?? '';
$deploymentId = $this->args['deploymentId'] ?? '';
Console::info("[ INFO ] Creating build for deployment: $deploymentId");
Console::info("Creating build for deployment: $deploymentId");
$this->buildDeployment($projectId, $functionId, $deploymentId);
break;
@ -45,7 +45,7 @@ class BuildsV1 extends Worker
$buildId = $this->args['buildId'] ?? '';
$functionId = $this->args['functionId'] ?? '';
$deploymentId = $this->args['deploymentId'] ?? '';
Console::info("[ INFO ] Retrying build for id: $buildId");
Console::info("Retrying build for id: $buildId");
$this->createBuild($projectId, $functionId, $deploymentId, $buildId);
break;
@ -113,28 +113,21 @@ class BuildsV1 extends Worker
if (empty($buildId)) {
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
$dbForProject->createDocument('builds', new Document([
'$id' => $buildId,
'$read' => [],
'$write' => [],
'dateCreated' => time(),
'startTime' => time(),
'deploymentId' => $deploymentId,
'status' => 'processing',
'runtime' => $function->getAttribute('runtime'),
'outputPath' => '',
'runtime' => $function->getAttribute('runtime'),
'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
]));
} catch (\Throwable $th) {
$deployment->setAttribute('buildId', '');
@ -154,7 +147,7 @@ class BuildsV1 extends Worker
throw $th;
}
Console::success("[ SUCCESS ] Build id: $buildId started");
Console::success("Build id: $buildId started");
}
public function shutdown(): void {}

View file

@ -8,11 +8,14 @@ use Appwrite\Resque\Worker;
use Utopia\Storage\Device\Local;
use Utopia\Abuse\Abuse;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\App;
use Utopia\CLI\Console;
use Utopia\Audit\Audit;
require_once __DIR__ . '/../init.php';
Authorization::disable();
Console::title('Deletes V1 Worker');
Console::success(APP_NAME . ' deletes worker v1 has started' . "\n");
@ -50,6 +53,9 @@ class DeletesV1 extends Worker
case DELETE_TYPE_FUNCTIONS:
$this->deleteFunction($document, $projectId);
break;
case DELETE_TYPE_DEPLOYMENTS:
$this->deleteDeployment($document, $projectId);
break;
case DELETE_TYPE_USERS:
$this->deleteUser($document, $projectId);
break;
@ -202,7 +208,7 @@ class DeletesV1 extends Worker
], $this->getProjectDB($projectId));
$user->setAttribute('sessions', []);
$updated = Authorization::skip(fn() => $this->getProjectDB($projectId)->updateDocument('users', $userId, $user));
$updated = $this->getProjectDB($projectId)->updateDocument('users', $userId, $user);
// Delete Memberships and decrement team membership counts
$this->deleteByGroup('memberships', [
@ -307,24 +313,139 @@ class DeletesV1 extends Worker
protected function deleteFunction(Document $document, string $projectId): void
{
$dbForProject = $this->getProjectDB($projectId);
$device = new Local(APP_STORAGE_FUNCTIONS . '/app-' . $projectId);
// Delete Deployments
/**
* Request executor to delete all deployment containers
*/
try {
$ch = \curl_init();
\curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
\curl_setopt($ch, CURLOPT_URL, "http://appwrite-executor/v1/functions/{$document->getId()}");
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
\curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'x-appwrite-project: '. $projectId,
'x-appwrite-executor-key: '. App::getEnv('_APP_EXECUTOR_SECRET', '')
]);
$executorResponse = \curl_exec($ch);
$error = \curl_error($ch);
if (!empty($error)) {
throw new Exception($error, 500);
}
$statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($statusCode >= 400) {
throw new Exception('Executor error: ' . $executorResponse, $statusCode);
}
\curl_close($ch);
} catch (Throwable $th) {
Console::error($th->getMessage());
}
/**
* Delete Deployments
*/
$storageFunctions = new Local(APP_STORAGE_FUNCTIONS . '/app-' . $projectId);
$deploymentIds = [];
$this->deleteByGroup('deployments', [
new Query('functionId', Query::TYPE_EQUAL, [$document->getId()])
], $dbForProject, function (Document $document) use ($device) {
if ($device->delete($document->getAttribute('path', ''))) {
Console::success('Delete code deployment: ' . $document->getAttribute('path', ''));
new Query('resourceId', Query::TYPE_EQUAL, [$document->getId()])
], $dbForProject, function (Document $document) use ($storageFunctions, &$deploymentIds) {
$deploymentIds[] = $document->getId();
if ($storageFunctions->delete($document->getAttribute('path', ''), true)) {
Console::success('Deleted deployment files: ' . $document->getAttribute('path', ''));
} else {
Console::error('Failed to delete code deployment: ' . $document->getAttribute('path', ''));
Console::error('Failed to delete deployment files: ' . $document->getAttribute('path', ''));
}
});
/**
* Delete builds
*/
if (!empty($deploymentIds)) {
$storageBuilds = new Local(APP_STORAGE_BUILDS . '/app-' . $projectId);
$this->deleteByGroup('builds', [
new Query('deploymentId', Query::TYPE_EQUAL, $deploymentIds)
], $dbForProject, function (Document $document) use ($storageBuilds) {
if ($storageBuilds->delete($document->getAttribute('outputPath', ''), true)) {
Console::success('Deleted build files: ' . $document->getAttribute('outputPath', ''));
} else {
Console::error('Failed to delete build files: ' . $document->getAttribute('outputPath', ''));
}
});
}
// Delete Executions
$this->deleteByGroup('executions', [
new Query('functionId', Query::TYPE_EQUAL, [$document->getId()])
], $dbForProject);
}
/**
* @param Document $document deployment document
* @param string $projectId
*/
protected function deleteDeployment(Document $document, string $projectId): void
{
$dbForProject = $this->getProjectDB($projectId);
/**
* Request executor to delete the deployment containers
*/
try {
$ch = \curl_init();
\curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
// TODO: Implement coroutines.
\curl_setopt($ch, CURLOPT_URL, "http://appwrite-executor/v1/deployments/{$document->getId()}");
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
\curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'x-appwrite-project: '. $projectId,
'x-appwrite-executor-key: '. App::getEnv('_APP_EXECUTOR_SECRET', '')
]);
$executorResponse = \curl_exec($ch);
$error = \curl_error($ch);
if (!empty($error)) {
throw new Exception($error, 500);
}
$statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($statusCode >= 400) {
throw new Exception('Executor error: ' . $executorResponse, $statusCode);
}
\curl_close($ch);
} catch (Throwable $th) {
Console::error($th->getMessage());
}
/**
* Delete deployment files
*/
$storageFunctions = new Local(APP_STORAGE_FUNCTIONS . '/app-' . $projectId);
if ($storageFunctions->delete($document->getAttribute('path', ''), true)) {
Console::success('Deleted deployment files: ' . $document->getAttribute('path', ''));
} else {
Console::error('Failed to delete deployment files: ' . $document->getAttribute('path', ''));
}
/**
* Delete builds
*/
$storageBuilds = new Local(APP_STORAGE_BUILDS . '/app-' . $projectId);
$this->deleteByGroup('builds', [
new Query('deploymentId', Query::TYPE_EQUAL, [$document->getId()])
], $dbForProject, function (Document $document) use ($storageBuilds) {
if ($storageBuilds->delete($document->getAttribute('outputPath', ''), true)) {
Console::success('Deleted build files: ' . $document->getAttribute('outputPath', ''));
} else {
Console::error('Failed to delete build files: ' . $document->getAttribute('outputPath', ''));
}
});
}
@ -337,8 +458,6 @@ class DeletesV1 extends Worker
*/
protected function deleteById(Document $document, Database $database, callable $callback = null): bool
{
Authorization::disable();
if ($database->deleteDocument($document->getCollection(), $document->getId())) {
Console::success('Deleted document "' . $document->getId() . '" successfully');
@ -351,8 +470,6 @@ class DeletesV1 extends Worker
Console::error('Failed to delete document: ' . $document->getId());
return false;
}
Authorization::reset();
}
/**
@ -369,9 +486,7 @@ class DeletesV1 extends Worker
$executionStart = \microtime(true);
while ($sum === $limit) {
Authorization::disable();
$projects = $this->getConsoleDB()->find('projects', [], $limit, ($chunk * $limit));
Authorization::reset();
$chunk++;
@ -410,12 +525,8 @@ class DeletesV1 extends Worker
while ($sum === $limit) {
$chunk++;
Authorization::disable();
$results = $database->find($collection, $queries, $limit, 0);
Authorization::reset();
$sum = count($results);
Console::info('Deleting chunk #' . $chunk . '. Found ' . $sum . ' documents');

View file

@ -238,6 +238,7 @@ services:
- appwrite-uploads:/storage/uploads:rw
- appwrite-cache:/storage/cache:rw
- appwrite-functions:/storage/functions:rw
- appwrite-builds:/storage/builds:rw
- appwrite-certificates:/storage/certificates:rw
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
@ -396,6 +397,7 @@ services:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- appwrite-functions:/storage/functions:rw
- appwrite-builds:/storage/builds:rw
- /tmp:/tmp:rw
- ./app:/usr/src/code/app
- ./src:/usr/src/code/src
@ -696,6 +698,7 @@ volumes:
appwrite-uploads:
appwrite-certificates:
appwrite-functions:
appwrite-builds:
appwrite-influxdb:
appwrite-config:
appwrite-executor:

View file

@ -87,7 +87,7 @@ class FunctionsCustomClientTest extends Scope
$this->assertEquals(201, $deployment['headers']['status-code']);
// Wait for deployment to be built.
sleep(5);
sleep(10);
$function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$function['body']['$id'].'/deployment', [
'content-type' => 'application/json',
@ -97,6 +97,8 @@ class FunctionsCustomClientTest extends Scope
'deployment' => $deploymentId,
]);
// var_dump($function);
$this->assertEquals(200, $function['headers']['status-code']);
$execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', [
@ -117,14 +119,14 @@ class FunctionsCustomClientTest extends Scope
$this->assertEquals(201, $execution['headers']['status-code']);
$execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', array_merge([
// Cleanup : Delete function
$response = $this->client->call(Client::METHOD_DELETE, '/functions/'.$function['body']['$id'], [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
]), [
'async' => true,
]);
'x-appwrite-key' => $this->getProject()['apiKey'],
], []);
$this->assertEquals(401, $execution['headers']['status-code']);
$this->assertEquals(204, $response['headers']['status-code']);
return [];
}
@ -300,6 +302,16 @@ class FunctionsCustomClientTest extends Scope
'cursor' => $base['body']['executions'][1]['$id'],
'cursorDirection' => Database::CURSOR_BEFORE
]);
// Cleanup : Delete function
$response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], []);
$this->assertEquals(204, $response['headers']['status-code']);
}
public function testSynchronousExecution():array
@ -346,7 +358,7 @@ class FunctionsCustomClientTest extends Scope
$this->assertEquals(201, $deployment['headers']['status-code']);
// Wait for deployment to be built.
sleep(5);
sleep(10);
$function = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployment', [
'content-type' => 'application/json',
@ -382,6 +394,15 @@ class FunctionsCustomClientTest extends Scope
$this->assertNotEmpty($output['APPWRITE_FUNCTION_JWT']);
$this->assertEquals($projectId, $output['APPWRITE_FUNCTION_PROJECT_ID']);
// Cleanup : Delete function
$response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], []);
$this->assertEquals(204, $response['headers']['status-code']);
return [];
}
}

View file

@ -291,10 +291,9 @@ class FunctionsCustomServerTest extends Scope
$this->assertNotEmpty($deployment['body']['$id']);
$this->assertIsInt($deployment['body']['dateCreated']);
$this->assertEquals('index.php', $deployment['body']['entrypoint']);
// $this->assertGreaterThan(10000, $deployment['body']['size']);
// Wait for deployment to build.
sleep(5);
sleep(15);
/**
* Test for FAILURE
@ -450,7 +449,7 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals('', $execution['body']['stderr']);
$this->assertEquals(0, $execution['body']['time']);
sleep(15);
sleep(5);
$execution = $this->client->call(Client::METHOD_GET, '/functions/'.$data['functionId'].'/executions/'.$executionId, array_merge([
'content-type' => 'application/json',
@ -628,7 +627,7 @@ class FunctionsCustomServerTest extends Scope
/**
* Test for SUCCESS
*/
$function = $this->client->call(Client::METHOD_DELETE, '/functions/'.$data['functionId'], array_merge([
$function = $this->client->call(Client::METHOD_DELETE, '/functions/'. $data['functionId'], array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
@ -686,7 +685,7 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals(201, $deployment['headers']['status-code']);
// Allow build step to run
sleep(5);
sleep(10);
$deployment = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployment', array_merge([
'content-type' => 'application/json',
@ -728,6 +727,15 @@ class FunctionsCustomServerTest extends Scope
$this->assertLessThan(3, $executions['body']['executions'][0]['time']);
$this->assertEquals($executions['body']['executions'][0]['stdout'], '');
$this->assertEquals($executions['body']['executions'][0]['stderr'], 'Execution timed out.');
// Cleanup : Delete function
$response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], []);
$this->assertEquals(204, $response['headers']['status-code']);
}
/**
@ -769,7 +777,7 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals(201, $deployment['headers']['status-code']);
// Allow build step to run
sleep(5);
sleep(10);
$deployment = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployment', array_merge([
'content-type' => 'application/json',
@ -829,6 +837,15 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals($executions['body']['executions'][0]['$id'], $executionId);
$this->assertEquals($executions['body']['executions'][0]['trigger'], 'http');
$this->assertStringContainsString('foobar', $executions['body']['executions'][0]['stdout']);
// Cleanup : Delete function
$response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], []);
$this->assertEquals(204, $response['headers']['status-code']);
}
public function testGetRuntimes()

View file

@ -36,7 +36,7 @@ class ComposeTest extends TestCase
public function testServices()
{
$this->assertCount(16, $this->object->getServices());
$this->assertCount(17, $this->object->getServices());
$this->assertEquals('appwrite-telegraf', $this->object->getService('telegraf')->getContainerName());
$this->assertEquals('appwrite', $this->object->getService('appwrite')->getContainerName());
$this->assertEquals('', $this->object->getService('appwrite')->getImageVersion());