diff --git a/.env b/.env index afa08f3ae9..d0a64ab8b2 100644 --- a/.env +++ b/.env @@ -54,7 +54,7 @@ _APP_FUNCTIONS_CPUS=1 _APP_FUNCTIONS_MEMORY=512 _APP_FUNCTIONS_INACTIVE_THRESHOLD=600 _APP_FUNCTIONS_MAINTENANCE_INTERVAL=600 -_APP_FUNCTIONS_RUNTIMES_NETWORK=openruntimes-runtimes +_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes _APP_EXECUTOR_SECRET=your-secret-key _APP_EXECUTOR_HOST=http://exc1/v1 _APP_FUNCTIONS_RUNTIMES= diff --git a/CHANGES.md b/CHANGES.md index 7a553d5d5e..e4a2a1ae49 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,39 @@ - Fix invited account verified status [#4776](https://github.com/appwrite/appwrite/pull/4776) - Get default region from environment on project create [#4780](https://github.com/appwrite/appwrite/pull/4780) - Fix max mimetype size [#4814](https://github.com/appwrite/appwrite/pull/4814) +- New usage metrics collection flow (https://github.com/appwrite/appwrite/pull/4770) + - Deprecated influxdb, statsd, telegraf containers and removed all of their occurrences from the code. + - Removed _APP_INFLUXDB_HOST, _APP_INFLUXDB_PORT, _APP_STATSD_HOST, _APP_STATSD_PORT env variables. + - Removed usage labels dependency. + - Usage metrics are processed via new usage worker. + - Metrics changes: + - Storage + - deprecated + - filesCreate, filesRead, filesUpdate, filesDelete, bucketsCreate, bucketsRead, bucketsUpdate, bucketsDelete. + - renamed + - filesCount to filesTotal, storage to filesStorage, bucketsCount to bucketsTotal. + - Auth + - deprecated + - usersCreate, usersRead, usersUpdate, usersDelete, sessionsCreate sessionsProviderCreate, sessionsDelete. + - renamed + - usersCount to usersTotal. + - added + - sessionsTotal. + - Databases + - deprecated + - databasesCreate, databasesRead, databasesDelete, documentsCreate, documentsRead, documentsUpdate, documentsDelete, collectionsCreate, collectionsRead, collectionsUpdate, collectionsDelete. + - renamed + - databasesCount to databasesTotal, collectionsCount to collectionsTotal, documentsCount to documentsTotal. + - Functions + - deprecated + - executionsFailure, executionsSuccess, buildsFailure, buildsSuccess, executionsFailure, executionsSuccess + - renamed + - executionsTime to executionsCompute, buildsTime to buildsCompute, documentsCount to documentsTotal. + - added + - functionsTotal, buildsStorage, deploymentsTotal, deploymentsStorage. + - Project + - renamed + - executions to executionsTotal, builds to buildsTotal, requests to requestsTotal, storage to filesStorage, buckets to bucketsTotal, users to usersTotal, documents to documentsTotal, collections to collectionsTotal, databases to databasesTotal. # Version 1.1.2 ## Changes diff --git a/Dockerfile b/Dockerfile index f52c116af3..4a9d07e422 100755 --- a/Dockerfile +++ b/Dockerfile @@ -307,7 +307,6 @@ RUN chmod +x /usr/local/bin/doctor && \ chmod +x /usr/local/bin/install && \ chmod +x /usr/local/bin/migrate && \ chmod +x /usr/local/bin/realtime && \ - chmod +x /usr/local/bin/executor && \ chmod +x /usr/local/bin/schedule && \ chmod +x /usr/local/bin/sdks && \ chmod +x /usr/local/bin/specs && \ diff --git a/app/config/collections.php b/app/config/collections.php index a96d7ed164..ba44e846e2 100644 --- a/app/config/collections.php +++ b/app/config/collections.php @@ -3,7 +3,7 @@ use Appwrite\Auth\Auth; use Utopia\Config\Config; use Utopia\Database\Database; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; $providers = Config::getParam('providers', []); $auth = Config::getParam('auth', []); @@ -192,7 +192,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -214,7 +214,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -369,7 +369,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -391,7 +391,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -496,7 +496,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -791,7 +791,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -892,7 +892,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -986,7 +986,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -1091,7 +1091,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -1203,7 +1203,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -1579,7 +1579,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -1673,7 +1673,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -2014,7 +2014,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -2036,7 +2036,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -2240,7 +2240,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -2284,7 +2284,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -2409,7 +2409,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -2442,7 +2442,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -2644,7 +2644,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -2760,7 +2760,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -2782,7 +2782,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], @@ -3669,7 +3669,7 @@ $collections = [ 'format' => '', 'size' => Database::LENGTH_KEY, 'signed' => true, - 'required' => false, + 'required' => true, 'default' => null, 'array' => false, 'filters' => [], diff --git a/app/console b/app/console index af3d741ae8..fae048b917 160000 --- a/app/console +++ b/app/console @@ -1 +1 @@ -Subproject commit af3d741ae8f02c2e16b8b4ea4664a3f8970290fd +Subproject commit fae048b91787d0b372c13caf27f14fc8b780ef60 diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 23f564667d..0895b3ed9e 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -29,10 +29,10 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\DateTime; use Utopia\Database\Exception\Duplicate; -use Utopia\Database\ID; -use Utopia\Database\Permission; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; use Utopia\Database\Query; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Locale\Locale; @@ -53,7 +53,6 @@ App::post('/v1/account/invite') ->label('audits.event', 'user.create') ->label('audits.resource', 'user/{response.$id}') ->label('audits.userId', '{response.$id}') - ->label('usage.metric', 'users.{scope}.requests.create') ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) ->label('sdk.namespace', 'account') ->label('sdk.method', 'createWithInviteCode') diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index d9312442ac..cf4160b6ce 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4,10 +4,10 @@ use Utopia\App; use Appwrite\Event\Delete; use Appwrite\Extend\Exception; use Utopia\Audit\Audit; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\DatetimeValidator; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; use Utopia\Validator\Boolean; use Utopia\Validator\FloatValidator; use Utopia\Validator\Integer; @@ -851,7 +851,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->param('collectionId', '', new UID(), 'Collection ID. You can create a new collection using the Database service [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection).') ->param('key', '', new Key(), 'Attribute Key.') ->param('size', null, new Range(1, APP_DATABASE_ATTRIBUTE_STRING_MAX_LENGTH, Range::TYPE_INTEGER), 'Attribute size for text attributes, in number of characters.') - ->param('required', null, new Boolean(true), 'Is attribute required?') + ->param('required', null, new Boolean(), 'Is attribute required?') ->param('default', null, new Text(0), 'Default value for attribute when not provided. Cannot be set when attribute is required.', true) ->param('array', false, new Boolean(), 'Is attribute an array?', true) ->inject('response') @@ -2385,6 +2385,74 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $response->noContent(); }); +App::get('/v1/databases/usage') + ->desc('Get usage stats for the database') + ->groups(['api', 'database']) + ->label('scope', 'collections.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'databases') + ->label('sdk.method', 'getUsage') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_USAGE_DATABASES) + ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), '`Date range.', true) + ->inject('response') + ->inject('dbForProject') + ->action(function (string $range, Response $response, Database $dbForProject) { + + $periods = Config::getParam('usage', []); + $stats = $usage = []; + $days = $periods[$range]; + $metrics = [ + METRIC_DATABASES, + METRIC_COLLECTIONS, + METRIC_DOCUMENTS, + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('period', [$period]), + Query::equal('metric', [$metric]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric] = []; + foreach ($results as $result) { + $stats[$metric][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + $response->dynamic(new Document([ + 'range' => $range, + 'databasesTotal' => $usage[$metrics[0]], + 'collectionsTotal' => $usage[$metrics[1]], + 'documentsTotal' => $usage[$metrics[2]], + ]), Response::MODEL_USAGE_DATABASES); + }); + App::get('/v1/databases/:databaseId/usage') ->desc('Get usage stats for the database') ->groups(['api', 'database']) @@ -2411,8 +2479,8 @@ App::get('/v1/databases/:databaseId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - $database->getInternalId() . '.collections', - $database->getInternalId() . '.documents', + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -2454,8 +2522,8 @@ App::get('/v1/databases/:databaseId/usage') $response->dynamic(new Document([ 'range' => $range, - 'collectionsCount' => $usage[$metrics[0]], - 'documentsCount' => $usage[$metrics[1]], + 'collectionsTotal' => $usage[$metrics[0]], + 'documentsTotal' => $usage[$metrics[1]], ]), Response::MODEL_USAGE_DATABASE); }); @@ -2478,7 +2546,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') ->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject) { $database = $dbForProject->getDocument('databases', $databaseId); - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); @@ -2490,7 +2557,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - $collectionDocument->getInternalId() . '.documents', + str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collectionDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -2532,74 +2599,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') $response->dynamic(new Document([ 'range' => $range, - 'documentsCount' => $usage[$metrics[0]], + 'documentsTotal' => $usage[$metrics[0]], ]), Response::MODEL_USAGE_COLLECTION); }); - -App::get('/v1/databases/usage') - ->desc('Get usage stats for the database') - ->groups(['api', 'database']) - ->label('scope', 'collections.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'databases') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_DATABASES) - ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d'], true), '`Date range.', true) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $range, Response $response, Database $dbForProject) { - - $periods = Config::getParam('usage', []); - $stats = $usage = []; - $days = $periods[$range]; - $metrics = [ - 'databases', - 'collections', - 'documents', - ]; - - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { - foreach ($metrics as $metric) { - $limit = $days['limit']; - $period = $days['period']; - $results = $dbForProject->find('stats', [ - Query::equal('period', [$period]), - Query::equal('metric', [$metric]), - Query::limit($limit), - Query::orderDesc('time'), - ]); - $stats[$metric] = []; - foreach ($results as $result) { - $stats[$metric][$result->getAttribute('time')] = [ - 'value' => $result->getAttribute('value'), - ]; - } - } - }); - - $format = match ($days['period']) { - '1h' => 'Y-m-d\TH:00:00.000P', - '1d' => 'Y-m-d\T00:00:00.000P', - }; - - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } - } - $response->dynamic(new Document([ - 'range' => $range, - 'databasesCount' => $usage[$metrics[0]], - 'collectionsCount' => $usage[$metrics[1]], - 'documentsCount' => $usage[$metrics[2]], - ]), Response::MODEL_USAGE_DATABASES); - }); diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index b0fd634f2d..2a849cef2c 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -10,9 +10,9 @@ use Appwrite\Event\Usage; use Appwrite\Event\Validator\Event as ValidatorEvent; use Appwrite\Extend\Exception; use Appwrite\Utopia\Database\Validator\CustomId; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\UID; use Utopia\Storage\Device; use Utopia\Storage\Validator\File; @@ -85,6 +85,7 @@ App::post('/v1/functions') 'deployment' => '', 'events' => $events, 'schedule' => $schedule, + 'scheduleInternalId' => '', 'scheduleUpdatedAt' => DateTime::now(), 'timeout' => $timeout, 'search' => implode(' ', [$functionId, $name, $runtime]) @@ -95,6 +96,7 @@ App::post('/v1/functions') 'region' => App::getEnv('_APP_REGION', 'default'), // Todo replace with projects region 'resourceType' => 'function', 'resourceId' => $function->getId(), + 'resourceInternalId' => $function->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $function->getAttribute('schedule'), @@ -210,6 +212,168 @@ App::get('/v1/functions/:functionId') $response->dynamic($function, Response::MODEL_FUNCTION); }); +App::get('/v1/functions/:functionId/usage') + ->desc('Get Function Usage') + ->groups(['api', 'functions']) + ->label('scope', 'functions.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'functions') + ->label('sdk.method', 'getFunctionUsage') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_USAGE_FUNCTIONS) + ->param('functionId', '', new UID(), 'Function ID.') + ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d']), 'Date range.', true) + ->inject('response') + ->inject('dbForProject') + ->action(function (string $functionId, string $range, Response $response, Database $dbForProject) { + + $function = $dbForProject->getDocument('functions', $functionId); + + if ($function->isEmpty()) { + throw new Exception(Exception::FUNCTION_NOT_FOUND); + } + + $periods = Config::getParam('usage', []); + $stats = $usage = []; + $days = $periods[$range]; + $metrics = [ + str_replace(['{resourceType}', '{resourceInternalId}'], ['function', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS), + str_replace(['{resourceType}', '{resourceInternalId}'], ['function', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), + str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), + str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), + str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), + str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), + str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('period', [$period]), + Query::equal('metric', [$metric]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric] = []; + foreach ($results as $result) { + $stats[$metric][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + + $response->dynamic(new Document([ + 'range' => $range, + 'deploymentsTotal' => $usage[$metrics[0]], + 'deploymentsStorage' => $usage[$metrics[1]], + 'buildsTotal' => $usage[$metrics[2]], + 'buildsStorage' => $usage[$metrics[3]], + 'buildsTime' => $usage[$metrics[4]], + 'executionsTotal' => $usage[$metrics[5]], + 'executionsTime' => $usage[$metrics[6]], + ]), Response::MODEL_USAGE_FUNCTION); + }); + +App::get('/v1/functions/usage') + ->desc('Get Functions Usage') + ->groups(['api', 'functions']) + ->label('scope', 'functions.read') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'functions') + ->label('sdk.method', 'getUsage') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_USAGE_FUNCTIONS) + ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d']), 'Date range.', true) + ->inject('response') + ->inject('dbForProject') + ->action(function (string $range, Response $response, Database $dbForProject) { + + $periods = Config::getParam('usage', []); + $stats = $usage = []; + $days = $periods[$range]; + $metrics = [ + METRIC_FUNCTIONS, + METRIC_DEPLOYMENTS, + METRIC_DEPLOYMENTS_STORAGE, + METRIC_BUILDS, + METRIC_BUILDS_STORAGE, + METRIC_BUILDS_COMPUTE, + METRIC_EXECUTIONS, + METRIC_EXECUTIONS_COMPUTE, + ]; + + Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { + foreach ($metrics as $metric) { + $limit = $days['limit']; + $period = $days['period']; + $results = $dbForProject->find('stats', [ + Query::equal('period', [$period]), + Query::equal('metric', [$metric]), + Query::limit($limit), + Query::orderDesc('time'), + ]); + $stats[$metric] = []; + foreach ($results as $result) { + $stats[$metric][$result->getAttribute('time')] = [ + 'value' => $result->getAttribute('value'), + ]; + } + } + }); + + $format = match ($days['period']) { + '1h' => 'Y-m-d\TH:00:00.000P', + '1d' => 'Y-m-d\T00:00:00.000P', + }; + + foreach ($metrics as $metric) { + $usage[$metric] = []; + $leap = time() - ($days['limit'] * $days['factor']); + while ($leap < time()) { + $leap += $days['factor']; + $formatDate = date($format, $leap); + $usage[$metric][] = [ + 'value' => $stats[$metric][$formatDate]['value'] ?? 0, + 'date' => $formatDate, + ]; + } + } + $response->dynamic(new Document([ + 'range' => $range, + 'functionsTotal' => $usage[$metrics[0]], + 'deploymentsTotal' => $usage[$metrics[1]], + 'deploymentsStorage' => $usage[$metrics[2]], + 'buildsTotal' => $usage[$metrics[3]], + 'buildsStorage' => $usage[$metrics[4]], + 'buildsTime' => $usage[$metrics[5]], + 'executionsTotal' => $usage[$metrics[6]], + 'executionsTime' => $usage[$metrics[7]], + ]), Response::MODEL_USAGE_FUNCTIONS); + }); + App::put('/v1/functions/:functionId') ->groups(['api', 'functions']) ->desc('Update Function') @@ -532,6 +696,7 @@ App::post('/v1/functions/:functionId/deployments') 'resourceInternalId' => $function->getInternalId(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', + 'buildInternalId' => '', 'entrypoint' => $entrypoint, 'path' => $path, 'size' => $fileSize, @@ -563,6 +728,7 @@ App::post('/v1/functions/:functionId/deployments') 'resourceInternalId' => $function->getInternalId(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', + 'buildInternalId' => '', 'entrypoint' => $entrypoint, 'path' => $path, 'size' => $fileSize, @@ -1006,8 +1172,8 @@ App::post('/v1/functions/:functionId/executions') * Sync execution compute usage from */ $queueForUsage - ->addMetric('executions.compute', (int)($executionResponse['duration'] * 1000))// per project - ->addMetric("{$function->getInternalId()}" . ".executions.compute", (int)($executionResponse['duration'] * 1000))// per function + ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($executionResponse['duration'] * 1000))// per project + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($executionResponse['duration'] * 1000))// per function ; } catch (\Throwable $th) { $interval = (new \DateTime())->diff(new \DateTime($execution->getCreatedAt())); @@ -1362,165 +1528,3 @@ App::delete('/v1/functions/:functionId/variables/:variableId') $response->noContent(); }); - -App::get('/v1/functions/:functionId/usage') - ->desc('Get Function Usage') - ->groups(['api', 'functions']) - ->label('scope', 'functions.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getFunctionUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_FUNCTIONS) - ->param('functionId', '', new UID(), 'Function ID.') - ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d']), 'Date range.', true) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $functionId, string $range, Response $response, Database $dbForProject) { - - $function = $dbForProject->getDocument('functions', $functionId); - - if ($function->isEmpty()) { - throw new Exception(Exception::FUNCTION_NOT_FOUND); - } - - $periods = Config::getParam('usage', []); - $stats = $usage = []; - $days = $periods[$range]; - $metrics = [ - 'functions.' . $function->getInternalId() . '.deployments', - 'functions.' . $function->getInternalId() . '.deployments.storage', - $function->getInternalId() . '.builds', - $function->getInternalId() . '.builds.storage', - $function->getInternalId() . '.builds.compute', - $function->getInternalId() . '.executions', - $function->getInternalId() . '.executions.compute', - ]; - - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { - foreach ($metrics as $metric) { - $limit = $days['limit']; - $period = $days['period']; - $results = $dbForProject->find('stats', [ - Query::equal('period', [$period]), - Query::equal('metric', [$metric]), - Query::limit($limit), - Query::orderDesc('time'), - ]); - $stats[$metric] = []; - foreach ($results as $result) { - $stats[$metric][$result->getAttribute('time')] = [ - 'value' => $result->getAttribute('value'), - ]; - } - } - }); - - $format = match ($days['period']) { - '1h' => 'Y-m-d\TH:00:00.000P', - '1d' => 'Y-m-d\T00:00:00.000P', - }; - - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } - } - - $response->dynamic(new Document([ - 'range' => $range, - 'deployments' => $usage[$metrics[0]], - 'deploymentsStorage' => $usage[$metrics[1]], - 'builds' => $usage[$metrics[2]], - 'buildsStorage' => $usage[$metrics[3]], - 'buildsCompute' => $usage[$metrics[4]], - 'executions' => $usage[$metrics[5]], - 'executionsCompute' => $usage[$metrics[6]], - ]), Response::MODEL_USAGE_FUNCTION); - }); - -App::get('/v1/functions/usage') - ->desc('Get Functions Usage') - ->groups(['api', 'functions']) - ->label('scope', 'functions.read') - ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) - ->label('sdk.namespace', 'functions') - ->label('sdk.method', 'getUsage') - ->label('sdk.response.code', Response::STATUS_CODE_OK) - ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) - ->label('sdk.response.model', Response::MODEL_USAGE_FUNCTIONS) - ->param('range', '30d', new WhiteList(['24h', '7d', '30d', '90d']), 'Date range.', true) - ->inject('response') - ->inject('dbForProject') - ->action(function (string $range, Response $response, Database $dbForProject) { - - $periods = Config::getParam('usage', []); - $stats = $usage = []; - $days = $periods[$range]; - $metrics = [ - 'functions', - 'deployments', - 'deployments.storage', - 'builds', - 'builds.storage', - 'builds.compute', - 'executions', - 'executions.compute', - ]; - - Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { - foreach ($metrics as $metric) { - $limit = $days['limit']; - $period = $days['period']; - $results = $dbForProject->find('stats', [ - Query::equal('period', [$period]), - Query::equal('metric', [$metric]), - Query::limit($limit), - Query::orderDesc('time'), - ]); - $stats[$metric] = []; - foreach ($results as $result) { - $stats[$metric][$result->getAttribute('time')] = [ - 'value' => $result->getAttribute('value'), - ]; - } - } - }); - - $format = match ($days['period']) { - '1h' => 'Y-m-d\TH:00:00.000P', - '1d' => 'Y-m-d\T00:00:00.000P', - }; - - foreach ($metrics as $metric) { - $usage[$metric] = []; - $leap = time() - ($days['limit'] * $days['factor']); - while ($leap < time()) { - $leap += $days['factor']; - $formatDate = date($format, $leap); - $usage[$metric][] = [ - 'value' => $stats[$metric][$formatDate]['value'] ?? 0, - 'date' => $formatDate, - ]; - } - } - $response->dynamic(new Document([ - 'range' => $range, - 'functions' => $usage[$metrics[0]], - 'deployments' => $usage[$metrics[1]], - 'deploymentsStorage' => $usage[$metrics[2]], - 'builds' => $usage[$metrics[3]], - 'buildsStorage' => $usage[$metrics[4]], - 'buildsCompute' => $usage[$metrics[5]], - 'executions' => $usage[$metrics[6]], - 'executionsCompute' => $usage[$metrics[7]], - ]), Response::MODEL_USAGE_FUNCTIONS); - }); diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 26ecf5d0f1..40b47b2913 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -29,15 +29,15 @@ App::get('/v1/project/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - 'network.requests', - 'network.inbound', - 'network.outbound', - 'executions', - 'documents', - 'databases', - 'users', - 'files.storage', - 'buckets', + METRIC_NETWORK_REQUESTS, + METRIC_NETWORK_INBOUND, + METRIC_NETWORK_OUTBOUND, + METRIC_EXECUTIONS, + METRIC_DOCUMENTS, + METRIC_DATABASES, + METRIC_USERS, + METRIC_BUCKETS, + METRIC_FILES_STORAGE ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -50,6 +50,7 @@ App::get('/v1/project/usage') Query::limit($limit), Query::orderDesc('time'), ]); + $stats[$metric] = []; foreach ($results as $result) { $stats[$metric][$result->getAttribute('time')] = [ @@ -59,6 +60,7 @@ App::get('/v1/project/usage') } }); + $format = match ($days['period']) { '1h' => 'Y-m-d\TH:00:00.000P', '1d' => 'Y-m-d\T00:00:00.000P', @@ -77,15 +79,16 @@ App::get('/v1/project/usage') } } + $response->dynamic(new Document([ 'range' => $range, - 'requests' => ($usage[$metrics[0]]), + 'requestsTotal' => ($usage[$metrics[0]]), 'network' => ($usage[$metrics[1]] + $usage[$metrics[2]]), - 'executions' => $usage[$metrics[3]], - 'documents' => $usage[$metrics[4]], - 'databases' => $usage[$metrics[5]], - 'users' => $usage[$metrics[6]], - 'storage' => $usage[$metrics[7]], - 'buckets' => $usage[$metrics[8]], + 'executionsTotal' => $usage[$metrics[3]], + 'documentsTotal' => $usage[$metrics[4]], + 'databasesTotal' => $usage[$metrics[5]], + 'usersTotal' => $usage[$metrics[6]], + 'bucketsTotal' => $usage[$metrics[7]], + 'filesStorage' => $usage[$metrics[8]], ]), Response::MODEL_USAGE_PROJECT); }); diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 5fef7eab78..8c2725fc1c 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -17,11 +17,11 @@ use Utopia\Audit\Audit; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; use Utopia\Database\DateTime; -use Utopia\Database\Permission; +use Utopia\Database\Helpers\Permission; use Utopia\Database\Query; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Domains\Domain; diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index dcf5900b46..7b17dce170 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -16,10 +16,10 @@ use Utopia\Database\Exception\Duplicate; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Exception\Structure as StructureException; -use Utopia\Database\ID; -use Utopia\Database\Permission; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; use Utopia\Database\Query; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; @@ -1439,8 +1439,8 @@ App::get('/v1/storage/:bucketId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - $bucket->getInternalId() . '.files', - $bucket->getInternalId() . '.files.storage', + str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES), + str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -1483,7 +1483,7 @@ App::get('/v1/storage/:bucketId/usage') $response->dynamic(new Document([ 'range' => $range, - 'filesCount' => $usage[$metrics[0]], + 'filesTotal' => $usage[$metrics[0]], 'filesStorage' => $usage[$metrics[1]], ]), Response::MODEL_USAGE_BUCKETS); }); @@ -1507,9 +1507,9 @@ App::get('/v1/storage/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - 'buckets', - 'files', - 'files.storage', + METRIC_BUCKETS, + METRIC_FILES, + METRIC_FILES_STORAGE, ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -1551,8 +1551,8 @@ App::get('/v1/storage/usage') $response->dynamic(new Document([ 'range' => $range, - 'bucketsCount' => $usage[$metrics[0]], - 'filesCount' => $usage[$metrics[1]], + 'bucketsTotal' => $usage[$metrics[0]], + 'filesTotal' => $usage[$metrics[1]], 'filesStorage' => $usage[$metrics[2]], ]), Response::MODEL_USAGE_STORAGE); }); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 572b6f02a8..9d202ad355 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -25,11 +25,11 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Authorization as AuthorizationException; use Utopia\Database\Exception\Duplicate; -use Utopia\Database\ID; -use Utopia\Database\Permission; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; use Utopia\Database\Query; use Utopia\Database\DateTime; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Key; use Utopia\Database\Validator\UID; diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 0df53a0dff..47b7b16947 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -16,9 +16,9 @@ use Appwrite\Utopia\Response; use Utopia\App; use Utopia\Audit\Audit; use Utopia\Config\Config; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; use Utopia\Locale\Locale; use Appwrite\Extend\Exception; use Utopia\Database\Document; @@ -1089,8 +1089,8 @@ App::get('/v1/users/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - 'users', - 'sessions', + METRIC_USERS, + METRIC_SESSIONS, ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -1132,7 +1132,7 @@ App::get('/v1/users/usage') $response->dynamic(new Document([ 'range' => $range, - 'usersCount' => $usage[$metrics[0]], - 'sessionsCount' => $usage[$metrics[1]], + 'usersTotal' => $usage[$metrics[0]], + 'sessionsTotal' => $usage[$metrics[1]], ]), Response::MODEL_USAGE_USERS); }); diff --git a/app/controllers/general.php b/app/controllers/general.php index d251e4ab93..9923fd74ff 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -3,7 +3,7 @@ require_once __DIR__ . '/../init.php'; use Utopia\App; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Role; use Utopia\Locale\Locale; use Utopia\Logger\Logger; use Utopia\Logger\Log; diff --git a/app/controllers/mock.php b/app/controllers/mock.php index 034f18165b..b980f09938 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -7,14 +7,13 @@ use Utopia\Database\Document; use Appwrite\Network\Validator\Host; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; -use Appwrite\Utopia\Response\Model; use Utopia\App; use Utopia\Validator\ArrayList; use Utopia\Validator\Integer; use Utopia\Validator\Text; use Utopia\Storage\Validator\File; use Utopia\Validator\WhiteList; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; App::get('/v1/mock/tests/foo') ->desc('Get Foo') diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 54f347f4a4..9eda797662 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -61,11 +61,11 @@ $databaseListener = function (string $event, Document $document, Document $proje switch (true) { case $document->getCollection() === 'teams': $queueForUsage - ->addMetric("teams", $value); // per project + ->addMetric(METRIC_TEAMS, $value); // per project break; case $document->getCollection() === 'users': $queueForUsage - ->addMetric("users", $value); // per project + ->addMetric(METRIC_USERS, $value); // per project if ($event === Database::EVENT_DOCUMENT_DELETE) { $queueForUsage ->addReduce($document); @@ -73,11 +73,11 @@ $databaseListener = function (string $event, Document $document, Document $proje break; case $document->getCollection() === 'sessions': // sessions $queueForUsage - ->addMetric("sessions", $value); //per project + ->addMetric(METRIC_SESSIONS, $value); //per project break; case $document->getCollection() === 'databases': // databases $queueForUsage - ->addMetric("databases", $value); // per project + ->addMetric(METRIC_DATABASES, $value); // per project if ($event === Database::EVENT_DOCUMENT_DELETE) { $queueForUsage @@ -86,10 +86,10 @@ $databaseListener = function (string $event, Document $document, Document $proje break; case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections $parts = explode('_', $document->getCollection()); - $databaseId = $parts[1] ?? 0; + $databaseInternalId = $parts[1] ?? 0; $queueForUsage - ->addMetric("collections", $value) // per project - ->addMetric("{$databaseId}" . ".collections", $value) // per database + ->addMetric(METRIC_COLLECTIONS, $value) // per project + ->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_COLLECTIONS), $value) // per database ; if ($event === Database::EVENT_DOCUMENT_DELETE) { @@ -99,16 +99,16 @@ $databaseListener = function (string $event, Document $document, Document $proje break; case str_starts_with($document->getCollection(), 'database_') && str_contains($document->getCollection(), '_collection_'): //documents $parts = explode('_', $document->getCollection()); - $databaseId = $parts[1] ?? 0; - $collectionId = $parts[3] ?? 0; + $databaseInternalId = $parts[1] ?? 0; + $collectionInternalId = $parts[3] ?? 0; $queueForUsage - ->addMetric("documents", $value) // per project - ->addMetric("{$databaseId}" . ".documents", $value) // per database - ->addMetric("{$databaseId}" . "." . "{$collectionId}" . ".documents", $value); // per collection + ->addMetric(METRIC_DOCUMENTS, $value) // per project + ->addMetric(str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_DOCUMENTS), $value) // per database + ->addMetric(str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $collectionInternalId], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), $value); // per collection break; case $document->getCollection() === 'buckets': //buckets $queueForUsage - ->addMetric("buckets", $value); // per project + ->addMetric(METRIC_BUCKETS, $value); // per project if ($event === Database::EVENT_DOCUMENT_DELETE) { $queueForUsage ->addReduce($document); @@ -116,16 +116,16 @@ $databaseListener = function (string $event, Document $document, Document $proje break; case str_starts_with($document->getCollection(), 'bucket_'): // files $parts = explode('_', $document->getCollection()); - $bucketId = $parts[1]; + $bucketInternalId = $parts[1]; $queueForUsage - ->addMetric("files", $value) // per project - ->addMetric("files.storage", $document->getAttribute('sizeOriginal') * $value) // per project - ->addMetric("{$bucketId}" . ".files", $value) // per bucket - ->addMetric("{$bucketId}" . ".files.storage", $document->getAttribute('sizeOriginal') * $value);// per bucket + ->addMetric(METRIC_FILES, $value) // per project + ->addMetric(METRIC_FILES_STORAGE, $document->getAttribute('sizeOriginal') * $value) // per project + ->addMetric(str_replace('{bucketInternalId}', $bucketInternalId, METRIC_BUCKET_ID_FILES), $value) // per bucket + ->addMetric(str_replace('{bucketInternalId}', $bucketInternalId, METRIC_BUCKET_ID_FILES_STORAGE), $document->getAttribute('sizeOriginal') * $value); // per bucket break; case $document->getCollection() === 'functions': $queueForUsage - ->addMetric('functions', $value); // per project + ->addMetric(METRIC_FUNCTIONS, $value); // per project if ($event === Database::EVENT_DOCUMENT_DELETE) { $queueForUsage @@ -134,15 +134,16 @@ $databaseListener = function (string $event, Document $document, Document $proje break; case $document->getCollection() === 'deployments': $queueForUsage - ->addMetric("deployments", $value) // per project - ->addMetric("deployments.storage", $document->getAttribute('size') * $value) // per project - ->addMetric("{$document->getAttribute('resourceType')}" . "." . "{$document->getAttribute('resourceInternalId')}" . ".deployments", $value)// per function - ->addMetric("{$document->getAttribute('resourceType')}" . "." . "{$document->getAttribute('resourceInternalId')}" . ".deployments.storage", $document->getAttribute('size') * $value); // per function + ->addMetric(METRIC_DEPLOYMENTS, $value) // per project + ->addMetric(METRIC_DEPLOYMENTS_STORAGE, $document->getAttribute('size') * $value) // per project + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS), $value)// per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getAttribute('resourceType'), $document->getAttribute('resourceInternalId')], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), $document->getAttribute('size') * $value);// per function + break; case $document->getCollection() === 'executions': $queueForUsage - ->addMetric("executions", $value) // per project - ->addMetric("{$document->getAttribute('functionInternalId')}" . ".executions", $value); // per function + ->addMetric(METRIC_EXECUTIONS, $value) // per project + ->addMetric(str_replace('{functionInternalId}', $document->getAttribute('functionInternalId'), METRIC_FUNCTION_ID_EXECUTIONS), $value);// per function break; default: break; @@ -513,19 +514,20 @@ App::shutdown() } } + + if ($project->getId() !== 'console') { if ($mode !== APP_MODE_ADMIN) { $fileSize = 0; $file = $request->getFiles('file'); - if (!empty($file)) { $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; } $queueForUsage - ->addMetric('network.requests', 1) - ->addMetric("network.inbound", $request->getSize() + $fileSize) - ->addMetric("network.outbound", $response->getSize()); + ->addMetric(METRIC_NETWORK_REQUESTS, 1) + ->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize) + ->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize()); } $queueForUsage diff --git a/app/executor.php b/app/executor.php deleted file mode 100644 index ded468b5d2..0000000000 --- a/app/executor.php +++ /dev/null @@ -1,803 +0,0 @@ -column('id', Swoole\Table::TYPE_STRING, 256); -$activeRuntimes->column('created', Swoole\Table::TYPE_INT, 8); -$activeRuntimes->column('updated', Swoole\Table::TYPE_INT, 8); -$activeRuntimes->column('name', Swoole\Table::TYPE_STRING, 128); -$activeRuntimes->column('status', Swoole\Table::TYPE_STRING, 128); -$activeRuntimes->column('key', Swoole\Table::TYPE_STRING, 256); -$activeRuntimes->create(); - -/** - * Create orchestration pool - */ -$orchestrationPool = new ConnectionPool(function () { - $dockerUser = App::getEnv('DOCKERHUB_PULL_USERNAME', null); - $dockerPass = App::getEnv('DOCKERHUB_PULL_PASSWORD', null); - $orchestration = new Orchestration(new DockerCLI($dockerUser, $dockerPass)); - return $orchestration; -}, 10); - - -/** - * Create logger instance - */ -$providerName = App::getEnv('_APP_LOGGING_PROVIDER', ''); -$providerConfig = App::getEnv('_APP_LOGGING_CONFIG', ''); -$logger = null; - -if (!empty($providerName) && !empty($providerConfig) && Logger::hasProvider($providerName)) { - $classname = '\\Utopia\\Logger\\Adapter\\' . \ucfirst($providerName); - $adapter = new $classname($providerConfig); - $logger = new Logger($adapter); -} - -function logError(Throwable $error, string $action, Utopia\Route $route = null) -{ - global $logger; - - if ($logger) { - $version = App::getEnv('_APP_VERSION', 'UNKNOWN'); - - $log = new Log(); - $log->setNamespace("executor"); - $log->setServer(\gethostname()); - $log->setVersion($version); - $log->setType(Log::TYPE_ERROR); - $log->setMessage($error->getMessage()); - - if ($route) { - $log->addTag('method', $route->getMethod()); - $log->addTag('url', $route->getPath()); - } - - $log->addTag('code', $error->getCode()); - $log->addTag('verboseType', get_class($error)); - - $log->addExtra('file', $error->getFile()); - $log->addExtra('line', $error->getLine()); - $log->addExtra('trace', $error->getTraceAsString()); - $log->addExtra('detailedTrace', $error->getTrace()); - - $log->setAction($action); - - $isProduction = App::getEnv('_APP_ENV', 'development') === 'production'; - $log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING); - - $responseCode = $logger->addLog($log); - Console::info('Executor log pushed with status code: ' . $responseCode); - } - - Console::error('[Error] Type: ' . get_class($error)); - Console::error('[Error] Message: ' . $error->getMessage()); - Console::error('[Error] File: ' . $error->getFile()); - Console::error('[Error] Line: ' . $error->getLine()); -} - -function getStorageDevice($root): Device -{ - switch (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL)) { - case Storage::DEVICE_LOCAL: - default: - return new Local($root); - case Storage::DEVICE_S3: - $s3AccessKey = App::getEnv('_APP_STORAGE_S3_ACCESS_KEY', ''); - $s3SecretKey = App::getEnv('_APP_STORAGE_S3_SECRET', ''); - $s3Region = App::getEnv('_APP_STORAGE_S3_REGION', ''); - $s3Bucket = App::getEnv('_APP_STORAGE_S3_BUCKET', ''); - $s3Acl = 'private'; - return new S3($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl); - case Storage::DEVICE_DO_SPACES: - $doSpacesAccessKey = App::getEnv('_APP_STORAGE_DO_SPACES_ACCESS_KEY', ''); - $doSpacesSecretKey = App::getEnv('_APP_STORAGE_DO_SPACES_SECRET', ''); - $doSpacesRegion = App::getEnv('_APP_STORAGE_DO_SPACES_REGION', ''); - $doSpacesBucket = App::getEnv('_APP_STORAGE_DO_SPACES_BUCKET', ''); - $doSpacesAcl = 'private'; - return new DOSpaces($root, $doSpacesAccessKey, $doSpacesSecretKey, $doSpacesBucket, $doSpacesRegion, $doSpacesAcl); - case Storage::DEVICE_BACKBLAZE: - $backblazeAccessKey = App::getEnv('_APP_STORAGE_BACKBLAZE_ACCESS_KEY', ''); - $backblazeSecretKey = App::getEnv('_APP_STORAGE_BACKBLAZE_SECRET', ''); - $backblazeRegion = App::getEnv('_APP_STORAGE_BACKBLAZE_REGION', ''); - $backblazeBucket = App::getEnv('_APP_STORAGE_BACKBLAZE_BUCKET', ''); - $backblazeAcl = 'private'; - return new Backblaze($root, $backblazeAccessKey, $backblazeSecretKey, $backblazeBucket, $backblazeRegion, $backblazeAcl); - case Storage::DEVICE_LINODE: - $linodeAccessKey = App::getEnv('_APP_STORAGE_LINODE_ACCESS_KEY', ''); - $linodeSecretKey = App::getEnv('_APP_STORAGE_LINODE_SECRET', ''); - $linodeRegion = App::getEnv('_APP_STORAGE_LINODE_REGION', ''); - $linodeBucket = App::getEnv('_APP_STORAGE_LINODE_BUCKET', ''); - $linodeAcl = 'private'; - return new Linode($root, $linodeAccessKey, $linodeSecretKey, $linodeBucket, $linodeRegion, $linodeAcl); - case Storage::DEVICE_WASABI: - $wasabiAccessKey = App::getEnv('_APP_STORAGE_WASABI_ACCESS_KEY', ''); - $wasabiSecretKey = App::getEnv('_APP_STORAGE_WASABI_SECRET', ''); - $wasabiRegion = App::getEnv('_APP_STORAGE_WASABI_REGION', ''); - $wasabiBucket = App::getEnv('_APP_STORAGE_WASABI_BUCKET', ''); - $wasabiAcl = 'private'; - return new Wasabi($root, $wasabiAccessKey, $wasabiSecretKey, $wasabiBucket, $wasabiRegion, $wasabiAcl); - } -} - -App::post('/v1/runtimes') - ->desc("Create a new runtime server") - ->param('runtimeId', '', new Text(64), 'Unique runtime ID.') - ->param('source', '', new Text(0), 'Path to source files.') - ->param('destination', '', new Text(0), 'Destination folder to store build files into.', true) - ->param('vars', [], new Assoc(), 'Environment Variables required for the build.') - ->param('commands', [], new ArrayList(new Text(1024), 100), 'Commands required to build the container. Maximum of 100 commands are allowed, each 1024 characters long.') - ->param('runtime', '', new Text(128), 'Runtime for the cloud function.') - ->param('baseImage', '', new Text(128), 'Base image name of the runtime.') - ->param('entrypoint', '', new Text(256), 'Entrypoint of the code file.', true) - ->param('remove', false, new Boolean(), 'Remove a runtime after execution.') - ->param('workdir', '', new Text(256), 'Working directory.', true) - ->inject('orchestrationPool') - ->inject('activeRuntimes') - ->inject('response') - ->action(function (string $runtimeId, string $source, string $destination, array $vars, array $commands, string $runtime, string $baseImage, string $entrypoint, bool $remove, string $workdir, $orchestrationPool, $activeRuntimes, Response $response) { - if ($activeRuntimes->exists($runtimeId)) { - if ($activeRuntimes->get($runtimeId)['status'] == 'pending') { - throw new \Exception('A runtime with the same ID is already being created. Attempt a execution soon.', 500); - } - - throw new Exception('Runtime already exists.', 409); - } - - $container = []; - $containerId = ''; - $stdout = ''; - $stderr = ''; - $startTime = DateTime::now(); - $startTimeUnix = (new \DateTime($startTime))->getTimestamp(); - $endTimeUnix = 0; - $orchestration = $orchestrationPool->get(); - - $secret = \bin2hex(\random_bytes(16)); - - if (!$remove) { - $activeRuntimes->set($runtimeId, [ - 'id' => $containerId, - 'name' => $runtimeId, - 'created' => $startTimeUnix, - 'updated' => $endTimeUnix, - 'status' => 'pending', - 'key' => $secret, - ]); - } - - try { - Console::info('Building container : ' . $runtimeId); - - /** - * Temporary file paths in the executor - */ - $tmpSource = "/tmp/$runtimeId/src/code.tar.gz"; - $tmpBuild = "/tmp/$runtimeId/builds/code.tar.gz"; - - /** - * Copy code files from source to a temporary location on the executor - */ - $sourceDevice = getStorageDevice("/"); - $localDevice = new Local(); - $buffer = $sourceDevice->read($source); - if (!$localDevice->write($tmpSource, $buffer)) { - throw new Exception('Failed to copy source code to temporary directory', 500); - }; - - /** - * Create the mount folder - */ - if (!\file_exists(\dirname($tmpBuild))) { - if (!@\mkdir(\dirname($tmpBuild), 0755, true)) { - throw new Exception("Failed to create temporary directory", 500); - } - } - - /** - * Create container - */ - $vars = \array_merge($vars, [ - 'INTERNAL_RUNTIME_KEY' => $secret, - 'INTERNAL_RUNTIME_ENTRYPOINT' => $entrypoint, - ]); - $vars = array_map(fn ($v) => strval($v), $vars); - $orchestration - ->setCpus((int) App::getEnv('_APP_FUNCTIONS_CPUS', 0)) - ->setMemory((int) App::getEnv('_APP_FUNCTIONS_MEMORY', 0)) - ->setSwap((int) App::getEnv('_APP_FUNCTIONS_MEMORY_SWAP', 0)); - - /** Keep the container alive if we have commands to be executed */ - $entrypoint = !empty($commands) ? [ - 'tail', - '-f', - '/dev/null' - ] : []; - - $containerId = $orchestration->run( - image: $baseImage, - name: $runtimeId, - hostname: $runtimeId, - vars: $vars, - command: $entrypoint, - labels: [ - 'openruntimes-id' => $runtimeId, - 'openruntimes-type' => 'runtime', - 'openruntimes-created' => strval($startTimeUnix), - 'openruntimes-runtime' => $runtime, - ], - workdir: $workdir, - volumes: [ - \dirname($tmpSource) . ':/tmp:rw', - \dirname($tmpBuild) . ':/usr/code:rw' - ] - ); - - if (empty($containerId)) { - throw new Exception('Failed to create build container', 500); - } - - $orchestration->networkConnect($runtimeId, App::getEnv('OPEN_RUNTIMES_NETWORK', 'appwrite_runtimes')); - - /** - * Execute any commands if they were provided - */ - if (!empty($commands)) { - $status = $orchestration->execute( - name: $runtimeId, - command: $commands, - stdout: $stdout, - stderr: $stderr, - timeout: App::getEnv('_APP_FUNCTIONS_BUILD_TIMEOUT', 900) - ); - - if (!$status) { - throw new Exception('Failed to build dependenices ' . $stderr, 500); - } - } - - /** - * Move built code to expected build directory - */ - if (!empty($destination)) { - // Check if the build was successful by checking if file exists - if (!\file_exists($tmpBuild)) { - throw new Exception('Something went wrong during the build process', 500); - } - - $destinationDevice = getStorageDevice($destination); - $outputPath = $destinationDevice->getPath(\uniqid() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); - - $buffer = $localDevice->read($tmpBuild); - if (!$destinationDevice->write($outputPath, $buffer, $localDevice->getFileMimeType($tmpBuild))) { - throw new Exception('Failed to move built code to storage', 500); - }; - - $container['outputPath'] = $outputPath; - } - - if (empty($stdout)) { - $stdout = 'Build Successful!'; - } - - $endTime = DateTime::now(); - $endTimeUnix = (new \DateTime($endTime))->getTimestamp(); - $duration = $endTimeUnix - $startTimeUnix; - - $container = array_merge($container, [ - 'status' => 'ready', - 'response' => \mb_strcut($stdout, 0, 1000000), // Limit to 1MB - 'stderr' => \mb_strcut($stderr, 0, 1000000), // Limit to 1MB - 'startTime' => $startTime, - 'endTime' => $endTime, - 'duration' => $duration, - ]); - - - if (!$remove) { - $activeRuntimes->set($runtimeId, [ - 'id' => $containerId, - 'name' => $runtimeId, - 'created' => $startTimeUnix, - 'updated' => $endTimeUnix, - 'status' => 'Up ' . \round($duration, 2) . 's', - 'key' => $secret, - ]); - } - - Console::success('Build Stage completed in ' . ($duration) . ' seconds'); - } catch (Throwable $th) { - Console::error('Build failed: ' . $th->getMessage() . $stdout); - - throw new Exception($th->getMessage() . $stdout, 500); - } finally { - // Container cleanup - if ($remove) { - if (!empty($containerId)) { - // If container properly created - $orchestration->remove($containerId, true); - $activeRuntimes->del($runtimeId); - } else { - // If whole creation failed, but container might have been initialized - try { - // Try to remove with contaier name instead of ID - $orchestration->remove($runtimeId, true); - $activeRuntimes->del($runtimeId); - } catch (Throwable $th) { - // If fails, means initialization also failed. - // Contianer is not there, no need to remove - } - } - } - - // Release orchestration back to pool, we are done with it - $orchestrationPool->put($orchestration); - } - - $response - ->setStatusCode(Response::STATUS_CODE_CREATED) - ->json($container); - }); - - -App::get('/v1/runtimes') - ->desc("List currently active runtimes") - ->inject('activeRuntimes') - ->inject('response') - ->action(function ($activeRuntimes, Response $response) { - $runtimes = []; - - foreach ($activeRuntimes as $runtime) { - $runtimes[] = $runtime; - } - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->json($runtimes); - }); - -App::get('/v1/runtimes/:runtimeId') - ->desc("Get a runtime by its ID") - ->param('runtimeId', '', new Text(64), 'Runtime unique ID.') - ->inject('activeRuntimes') - ->inject('response') - ->action(function ($runtimeId, $activeRuntimes, Response $response) { - - if (!$activeRuntimes->exists($runtimeId)) { - throw new Exception('Runtime not found', 404); - } - - $runtime = $activeRuntimes->get($runtimeId); - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->json($runtime); - }); - -App::delete('/v1/runtimes/:runtimeId') - ->desc('Delete a runtime') - ->param('runtimeId', '', new Text(64), 'Runtime unique ID.', false) - ->inject('orchestrationPool') - ->inject('activeRuntimes') - ->inject('response') - ->action(function (string $runtimeId, $orchestrationPool, $activeRuntimes, Response $response) { - - if (!$activeRuntimes->exists($runtimeId)) { - throw new Exception('Runtime not found', 404); - } - - Console::info('Deleting runtime: ' . $runtimeId); - - try { - $orchestration = $orchestrationPool->get(); - $orchestration->remove($runtimeId, true); - $activeRuntimes->del($runtimeId); - Console::success('Removed runtime container: ' . $runtimeId); - } finally { - $orchestrationPool->put($orchestration); - } - - // Remove all the build containers with that same ID - // TODO:: Delete build containers - // foreach ($buildIds as $buildId) { - // try { - // Console::info('Deleting build container : ' . $buildId); - // $status = $orchestration->remove('build-' . $buildId, true); - // } catch (Throwable $th) { - // Console::error($th->getMessage()); - // } - // } - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->send(); - }); - - -App::post('/v1/execution') - ->desc('Create an execution') - ->param('runtimeId', '', new Text(64), 'The runtimeID to execute.') - ->param('vars', [], new Assoc(), 'Environment variables required for the build.') - ->param('data', '', new Text(8192), 'Data to be forwarded to the function, this is user specified.', true) - ->param('timeout', 15, new Range(1, (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)), 'Function maximum execution time in seconds.') - ->inject('activeRuntimes') - ->inject('response') - ->action( - function (string $runtimeId, array $vars, string $data, $timeout, $activeRuntimes, Response $response) { - if (!$activeRuntimes->exists($runtimeId)) { - throw new Exception('Runtime not found. Please create the runtime.', 404); - } - - for ($i = 0; $i < 5; $i++) { - if ($activeRuntimes->get($runtimeId)['status'] === 'pending') { - Console::info('Waiting for runtime to be ready...'); - sleep(1); - } else { - break; - } - - if ($i === 4) { - throw new Exception('Runtime failed to launch in allocated time.', 500); - } - } - - $runtime = $activeRuntimes->get($runtimeId); - $secret = $runtime['key']; - if (empty($secret)) { - throw new Exception('Runtime secret not found. Please re-create the runtime.', 500); - } - - Console::info('Executing Runtime: ' . $runtimeId); - - $execution = []; - $executionStart = \microtime(true); - $stdout = ''; - $stderr = ''; - $res = ''; - $statusCode = 0; - $errNo = -1; - $executorResponse = ''; - - $timeout ??= (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900); - - $ch = \curl_init(); - $body = \json_encode([ - 'variables' => $vars, - 'payload' => $data, - 'timeout' => $timeout - ]); - \curl_setopt($ch, CURLOPT_URL, "http://" . $runtimeId . ":3000/"); - \curl_setopt($ch, CURLOPT_POST, true); - \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); - \curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - \curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); - \curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); - - \curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'Content-Length: ' . \strlen($body), - 'x-internal-challenge: ' . $secret, - 'host: null' - ]); - - $executorResponse = \curl_exec($ch); - $executorResponse = json_decode($executorResponse, true); - - $statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE); - - $error = \curl_error($ch); - - $errNo = \curl_errno($ch); - - \curl_close($ch); - - switch (true) { - /** No Error. */ - 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); - /** Any other CURL error */ - default: - throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 500); - } - - switch (true) { - case $statusCode >= 500: - $stderr = ($executorResponse ?? [])['stderr'] ?? 'Internal Runtime error.'; - $stdout = ($executorResponse ?? [])['stdout'] ?? 'Internal Runtime error.'; - break; - case $statusCode >= 100: - $stdout = $executorResponse['stdout']; - $res = $executorResponse['response']; - if (is_array($res)) { - $res = json_encode($res, JSON_UNESCAPED_UNICODE); - } - break; - default: - $stderr = ($executorResponse ?? [])['stderr'] ?? 'Execution failed.'; - $stdout = ($executorResponse ?? [])['stdout'] ?? ''; - break; - } - - $executionEnd = \microtime(true); - $executionTime = ($executionEnd - $executionStart); - $functionStatus = ($statusCode >= 500) ? 'failed' : 'completed'; - - Console::success('Function executed in ' . $executionTime . ' seconds, status: ' . $functionStatus); - - $execution = [ - 'status' => $functionStatus, - 'statusCode' => $statusCode, - 'response' => \mb_strcut($res, 0, 1000000), // Limit to 1MB - 'stdout' => \mb_strcut($stdout, 0, 1000000), // Limit to 1MB - 'stderr' => \mb_strcut($stderr, 0, 1000000), // Limit to 1MB - 'duration' => $executionTime, - ]; - - /** Update swoole table */ - $runtime['updated'] = \time(); - $activeRuntimes->set($runtimeId, $runtime); - - $response - ->setStatusCode(Response::STATUS_CODE_OK) - ->json($execution); - } - ); - -App::setMode(App::MODE_TYPE_PRODUCTION); // Define Mode - -$http = new Server("0.0.0.0", 80); - -/** Set Resources */ -App::setResource('orchestrationPool', fn() => $orchestrationPool); -App::setResource('activeRuntimes', fn() => $activeRuntimes); - -/** Set callbacks */ -App::error() - ->inject('utopia') - ->inject('error') - ->inject('request') - ->inject('response') - ->action(function (App $utopia, throwable $error, Request $request, Response $response) { - $route = $utopia->match($request); - logError($error, "httpError", $route); - - switch ($error->getCode()) { - case 400: // Error allowed publicly - case 401: // Error allowed publicly - case 402: // Error allowed publicly - case 403: // Error allowed publicly - case 404: // Error allowed publicly - case 406: // Error allowed publicly - case 409: // Error allowed publicly - case 412: // Error allowed publicly - case 425: // Error allowed publicly - case 429: // Error allowed publicly - case 501: // Error allowed publicly - case 503: // Error allowed publicly - $code = $error->getCode(); - break; - default: - $code = 500; // All other errors get the generic 500 server error status code - } - - $output = [ - 'message' => $error->getMessage(), - 'code' => $error->getCode(), - 'file' => $error->getFile(), - 'line' => $error->getLine(), - 'trace' => $error->getTrace(), - 'version' => App::getEnv('_APP_VERSION', 'UNKNOWN') - ]; - - $response - ->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') - ->addHeader('Expires', '0') - ->addHeader('Pragma', 'no-cache') - ->setStatusCode($code); - - $response->json($output); - }); - -App::init() - ->inject('request') - ->action(function (Request $request) { - $secretKey = $request->getHeader('x-appwrite-executor-key', ''); - if (empty($secretKey)) { - throw new Exception('Missing executor key', 401); - } - - if ($secretKey !== App::getEnv('_APP_EXECUTOR_SECRET', '')) { - throw new Exception('Missing executor key', 401); - } - }); - - -$http->on('start', function ($http) { - global $orchestrationPool; - global $activeRuntimes; - - /** - * Warmup: make sure images are ready to run fast 🚀 - */ - $runtimes = new Runtimes('v2'); - $allowList = empty(App::getEnv('_APP_FUNCTIONS_RUNTIMES')) ? [] : \explode(',', App::getEnv('_APP_FUNCTIONS_RUNTIMES')); - $runtimes = $runtimes->getAll(true, $allowList); - foreach ($runtimes as $runtime) { - go(function () use ($runtime, $orchestrationPool) { - try { - $orchestration = $orchestrationPool->get(); - Console::info('Warming up ' . $runtime['name'] . ' ' . $runtime['version'] . ' environment...'); - $response = $orchestration->pull($runtime['image']); - if ($response) { - Console::success("Successfully Warmed up {$runtime['name']} {$runtime['version']}!"); - } else { - Console::warning("Failed to Warmup {$runtime['name']} {$runtime['version']}!"); - } - } catch (\Throwable $th) { - } finally { - $orchestrationPool->put($orchestration); - } - }); - } - - /** - * Remove residual runtimes - */ - Console::info('Removing orphan runtimes...'); - try { - $orchestration = $orchestrationPool->get(); - $orphans = $orchestration->list(['label' => 'openruntimes-type=runtime']); - } finally { - $orchestrationPool->put($orchestration); - } - - foreach ($orphans as $runtime) { - go(function () use ($runtime, $orchestrationPool) { - try { - $orchestration = $orchestrationPool->get(); - $orchestration->remove($runtime->getName(), true); - Console::success("Successfully removed {$runtime->getName()}"); - } catch (\Throwable $th) { - Console::error('Orphan runtime deletion failed: ' . $th->getMessage()); - } finally { - $orchestrationPool->put($orchestration); - } - }); - } - - /** - * Register handlers for shutdown - */ - @Process::signal(SIGINT, function () use ($http) { - $http->shutdown(); - }); - - @Process::signal(SIGQUIT, function () use ($http) { - $http->shutdown(); - }); - - @Process::signal(SIGKILL, function () use ($http) { - $http->shutdown(); - }); - - @Process::signal(SIGTERM, function () use ($http) { - $http->shutdown(); - }); - - /** - * Run a maintenance worker every MAINTENANCE_INTERVAL seconds to remove inactive runtimes - */ - Timer::tick(MAINTENANCE_INTERVAL * 1000, function () use ($orchestrationPool, $activeRuntimes) { - Console::warning("Running maintenance task ..."); - foreach ($activeRuntimes as $runtime) { - $inactiveThreshold = \time() - App::getEnv('_APP_FUNCTIONS_INACTIVE_THRESHOLD', 60); - if ($runtime['updated'] < $inactiveThreshold) { - go(function () use ($runtime, $orchestrationPool, $activeRuntimes) { - try { - $orchestration = $orchestrationPool->get(); - $orchestration->remove($runtime['name'], true); - $activeRuntimes->del($runtime['name']); - Console::success("Successfully removed {$runtime['name']}"); - } catch (\Throwable $th) { - Console::error('Inactive Runtime deletion failed: ' . $th->getMessage()); - } finally { - $orchestrationPool->put($orchestration); - } - }); - } - } - }); -}); - - -$http->on('beforeShutdown', function () { - global $orchestrationPool; - Console::info('Cleaning up containers before shutdown...'); - - $orchestration = $orchestrationPool->get(); - $functionsToRemove = $orchestration->list(['label' => 'openruntimes-type=runtime']); - $orchestrationPool->put($orchestration); - - foreach ($functionsToRemove as $container) { - go(function () use ($orchestrationPool, $container) { - try { - $orchestration = $orchestrationPool->get(); - $orchestration->remove($container->getId(), true); - Console::info('Removed container ' . $container->getName()); - } catch (\Throwable $th) { - Console::error('Failed to remove container: ' . $container->getName()); - } finally { - $orchestrationPool->put($orchestration); - } - }); - } -}); - - -$http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) { - $request = new Request($swooleRequest); - $response = new Response($swooleResponse); - $app = new App('UTC'); - - try { - $app->run($request, $response); - } catch (\Throwable $th) { - logError($th, "serverError"); - $swooleResponse->setStatusCode(500); - $output = [ - 'message' => 'Error: ' . $th->getMessage(), - 'code' => 500, - 'file' => $th->getFile(), - 'line' => $th->getLine(), - 'trace' => $th->getTrace() - ]; - $swooleResponse->end(\json_encode($output)); - } -}); - -$http->start(); diff --git a/app/http.php b/app/http.php index 23fd0dbcc9..f241b9e155 100644 --- a/app/http.php +++ b/app/http.php @@ -10,9 +10,9 @@ use Swoole\Http\Response as SwooleResponse; use Utopia\App; use Utopia\CLI\Console; use Utopia\Config\Config; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Audit\Audit; use Utopia\Abuse\Adapters\TimeLimit; diff --git a/app/init.php b/app/init.php index 1728fb2b8a..7643638d9e 100644 --- a/app/init.php +++ b/app/init.php @@ -41,7 +41,7 @@ use Appwrite\URL\URL as AppwriteURL; use Utopia\App; use Utopia\Validator\Range; use Utopia\Validator\WhiteList; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; use Utopia\Database\Document; use Utopia\Database\Database; use Utopia\Database\Query; @@ -174,6 +174,39 @@ const APP_AUTH_TYPE_KEY = 'Key'; const APP_AUTH_TYPE_ADMIN = 'Admin'; // Response related const MAX_OUTPUT_CHUNK_SIZE = 2 * 1024 * 1024; // 2MB +// Usage metrics +const METRIC_TEAMS = 'teams'; +const METRIC_USERS = 'users'; +const METRIC_SESSIONS = 'sessions'; +const METRIC_DATABASES = 'databases'; +const METRIC_COLLECTIONS = 'collections'; +const METRIC_DATABASE_ID_COLLECTIONS = '{databaseInternalId}.collections'; +const METRIC_DOCUMENTS = 'documents'; +const METRIC_DATABASE_ID_DOCUMENTS = '{databaseInternalId}.documents'; +const METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS = '{databaseInternalId}.{collectionInternalId}.documents'; +const METRIC_BUCKETS = 'buckets'; +const METRIC_FILES = 'files'; +const METRIC_FILES_STORAGE = 'files.storage'; +const METRIC_BUCKET_ID_FILES = '{bucketInternalId}.files'; +const METRIC_BUCKET_ID_FILES_STORAGE = '{bucketInternalId}.files.storage'; +const METRIC_FUNCTIONS = 'functions'; +const METRIC_DEPLOYMENTS = 'deployments'; +const METRIC_DEPLOYMENTS_STORAGE = 'deployments.storage'; +const METRIC_BUILDS = 'builds'; +const METRIC_BUILDS_STORAGE = 'builds.storage'; +const METRIC_BUILDS_COMPUTE = 'builds.compute'; +const METRIC_FUNCTION_ID_BUILDS = '{functionInternalId}.builds'; +const METRIC_FUNCTION_ID_BUILDS_STORAGE = '{functionInternalId}.builds.storage'; +const METRIC_FUNCTION_ID_BUILDS_COMPUTE = '{functionInternalId}.builds.compute'; +const METRIC_FUNCTION_ID_DEPLOYMENTS = '{resourceType}.{resourceInternalId}.deployments'; +const METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE = '{resourceType}.{resourceInternalId}.deployments.storage'; +const METRIC_EXECUTIONS = 'executions'; +const METRIC_EXECUTIONS_COMPUTE = 'executions.compute'; +const METRIC_FUNCTION_ID_EXECUTIONS = '{functionInternalId}.executions'; +const METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE = '{functionInternalId}.executions.compute'; +const METRIC_NETWORK_REQUESTS = 'network.requests'; +const METRIC_NETWORK_INBOUND = 'network.inbound'; +const METRIC_NETWORK_OUTBOUND = 'network.outbound'; $register = new Registry(); diff --git a/app/realtime.php b/app/realtime.php index 4b40e2a9dd..f7f40de84c 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -13,8 +13,8 @@ use Utopia\Abuse\Abuse; use Utopia\Abuse\Adapters\TimeLimit; use Utopia\App; use Utopia\CLI\Console; -use Utopia\Database\ID; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Role; use Utopia\Logger\Log; use Utopia\Database\DateTime; use Utopia\Database\Document; diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index bff03a2b61..dc058e78d6 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -80,7 +80,6 @@ services: - mariadb - redis # - clamav - - influxdb environment: - _APP_ENV - _APP_WORKER_PER_CORE @@ -430,42 +429,6 @@ services: - _APP_LOGGING_PROVIDER - _APP_LOGGING_CONFIG - appwrite-worker-usage: - image: /: - entrypoint: worker-usage - <<: *x-logging - container_name: appwrite-worker-usage - networks: - - appwrite - volumes: - - ./app:/usr/src/code/app - - ./src:/usr/src/code/src - depends_on: - - redis - - mariadb - environment: - - _APP_ENV - - _APP_WORKER_PER_CORE - - _APP_CONNECTIONS_MAX - - _APP_POOL_CLIENTS - - _APP_OPENSSL_KEY_V1 - - _APP_DB_HOST - - _APP_DB_PORT - - _APP_DB_SCHEMA - - _APP_DB_USER - - _APP_DB_PASS - - _APP_REDIS_HOST - - _APP_REDIS_PORT - - _APP_REDIS_USER - - _APP_REDIS_PASS - - _APP_CONNECTIONS_DB_CONSOLE - - _APP_CONNECTIONS_DB_PROJECT - - _APP_CONNECTIONS_CACHE - - _APP_CONNECTIONS_QUEUE - - _APP_USAGE_STATS - - DOCKERHUB_PULL_USERNAME - - DOCKERHUB_PULL_PASSWORD - appwrite-maintenance: image: /: entrypoint: maintenance @@ -581,6 +544,42 @@ services: # volumes: # - appwrite-uploads:/storage/uploads + appwrite-worker-usage: + image: /: + entrypoint: worker-usage + <<: *x-logging + container_name: appwrite-worker-usage + networks: + - appwrite + volumes: + - ./app:/usr/src/code/app + - ./src:/usr/src/code/src + depends_on: + - redis + - mariadb + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_CONNECTIONS_MAX + - _APP_POOL_CLIENTS + - _APP_OPENSSL_KEY_V1 + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_CONNECTIONS_DB_CONSOLE + - _APP_CONNECTIONS_DB_PROJECT + - _APP_CONNECTIONS_CACHE + - _APP_CONNECTIONS_QUEUE + - _APP_USAGE_STATS + - DOCKERHUB_PULL_USERNAME + - DOCKERHUB_PULL_PASSWORD + networks: gateway: name: gateway diff --git a/app/workers/builds.php b/app/workers/builds.php index cf027777a2..a2b29c0ab8 100644 --- a/app/workers/builds.php +++ b/app/workers/builds.php @@ -9,7 +9,7 @@ use Executor\Executor; use Utopia\Database\DateTime; use Utopia\App; use Utopia\CLI\Console; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; use Utopia\DSN\DSN; use Utopia\Database\Document; use Utopia\Config\Config; @@ -56,6 +56,11 @@ class BuildsV1 extends Worker } } + /** + * @throws \Utopia\Database\Exception\Authorization + * @throws \Utopia\Database\Exception\Structure + * @throws Throwable + */ protected function buildDeployment(Document $project, Document $function, Document $deployment) { global $register; @@ -171,8 +176,8 @@ class BuildsV1 extends Worker try { $response = $this->executor->createRuntime( - projectId: $project->getId(), deploymentId: $deployment->getId(), + projectId: $project->getId(), source: $source, image: $runtime['image'], remove: true, @@ -256,12 +261,12 @@ class BuildsV1 extends Worker $this ->getUsageQueue() ->setProject($project) - ->addMetric("builds", 1) // per project - ->addMetric("builds.storage", $build->getAttribute('size', 0)) - ->addMetric("builds.compute", $build->getAttribute('duration', 0)) - ->addMetric("{$function->getInternalId()}" . ".builds", 1) // per function - ->addMetric("{$function->getInternalId()}" . ".builds.storage", $build->getAttribute('size', 0)) - ->addMetric("{$function->getInternalId()}" . ".builds.compute", $build->getAttribute('duration', 0)) + ->addMetric(METRIC_BUILDS, 1) // per project + ->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0)) + ->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000) + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1) // per function + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) ->trigger() ; } diff --git a/app/workers/certificates.php b/app/workers/certificates.php index b4f0701c46..60ee3e8e0b 100644 --- a/app/workers/certificates.php +++ b/app/workers/certificates.php @@ -8,7 +8,7 @@ use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\DateTime; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; use Utopia\Database\Query; use Utopia\Domains\Domain; diff --git a/app/workers/functions.php b/app/workers/functions.php index 368e4a4e7c..724c05a828 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -14,10 +14,10 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\ID; -use Utopia\Database\Permission; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; use Utopia\Database\Query; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Queue\Server; @@ -103,8 +103,8 @@ Server::setResource('execute', function () { */ $queueForUsage - ->addMetric('executions', 1) // per project - ->addMetric("{$function->getId()}" . ".executions", 1); // per function + ->addMetric(METRIC_EXECUTIONS, 1) // per project + ->addMetric(str_replace('{functionInternalId}', $function->getId(), METRIC_FUNCTION_ID_EXECUTIONS), 1); // per function } $execution->setAttribute('status', 'processing'); @@ -214,8 +214,8 @@ Server::setResource('execute', function () { /** Trigger usage queue */ $queueForUsage ->setProject($project) - ->addMetric('executions.compute', (int)($execution->getAttribute('duration') * 1000))// per project - ->addMetric("{$function->getInternalId()}" . ".executions.compute", (int)($execution->getAttribute('duration') * 1000))// per function + ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000))// per project + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) ->trigger() ; }; diff --git a/app/workers/usage.php b/app/workers/usage.php index 127f58a7cf..c2dea662e7 100644 --- a/app/workers/usage.php +++ b/app/workers/usage.php @@ -25,6 +25,8 @@ $periods['1d'] = 'Y-m-d 00:00'; //$periods['1m'] = 'Y-m-1 00:00'; $periods['inf'] = '0000-00-00 00:00'; +const INFINITI_PERIOD = '_inf_'; + /** * On Documents that tied by relations like functions>deployments>build || documents>collection>database || buckets>files * When we remove a parent document we need to deduct his children aggregation from the project scope @@ -44,121 +46,121 @@ Server::setResource('reduce', function (Cache $cache, Registry $register, $pools switch (true) { case $document->getCollection() === 'users': // users - $sessions = count($document->getAttribute('sessions', 0)); + $sessions = count($document->getAttribute(METRIC_SESSIONS, 0)); if (!empty($sessions)) { $metrics[] = [ - 'key' => 'sessions', + 'key' => METRIC_SESSIONS, 'value' => ($sessions * -1), ]; } break; case $document->getCollection() === 'databases': // databases - $collections = $dbForProject->getDocument('stats', md5("_inf_" . "{$document->getInternalId()}" . ".collections")); - $documents = $dbForProject->getDocument('stats', md5("_inf_" . "{$document->getInternalId()}" . ".documents")); + $collections = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); + $documents = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); if (!empty($collections['value'])) { $metrics[] = [ - 'key' => 'collections', + 'key' => METRIC_COLLECTIONS, 'value' => ($collections['value'] * -1), ]; } if (!empty($documents['value'])) { $metrics[] = [ - 'key' => 'documents', + 'key' => METRIC_DOCUMENTS, 'value' => ($documents['value'] * -1), ]; } break; case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections $parts = explode('_', $document->getCollection()); - $databaseId = $parts[1] ?? 0; - $documents = $dbForProject->getDocument('stats', md5("_inf_" . "{$databaseId}" . "." . "{$document->getInternalId()}" . ".documents")); + $databaseInternalId = $parts[1] ?? 0; + $documents = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); if (!empty($documents['value'])) { $metrics[] = [ - 'key' => 'documents', + 'key' => METRIC_DOCUMENTS, 'value' => ($documents['value'] * -1), ]; $metrics[] = [ - 'key' => "{$databaseId}" . ".documents", + 'key' => str_replace('{databaseInternalId}', $databaseInternalId, METRIC_DATABASE_ID_DOCUMENTS), 'value' => ($documents['value'] * -1), ]; } break; case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats', md5("_inf_" . "{$document->getInternalId()}" . ".files")); - $storage = $dbForProject->getDocument('stats', md5("_inf_" . "{$document->getInternalId()}" . ".files.storage")); + $files = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); if (!empty($files['value'])) { $metrics[] = [ - 'key' => 'files', + 'key' => METRIC_FILES, 'value' => ($files['value'] * -1), ]; } if (!empty($storage['value'])) { $metrics[] = [ - 'key' => 'files.storage', + 'key' => METRIC_FILES_STORAGE, 'value' => ($storage['value'] * -1), ]; } break; case $document->getCollection() === 'functions': - $deployments = $dbForProject->getDocument('stats', md5("_inf_function." . "{$document->getInternalId()}" . ".deployments")); - $deploymentsStorage = $dbForProject->getDocument('stats', md5("_inf_function." . "{$document->getInternalId()}" . ".deployments.storage")); - $builds = $dbForProject->getDocument('stats', md5("_inf_" . "{$document->getInternalId()}" . ".builds")); - $buildsStorage = $dbForProject->getDocument('stats', md5("_inf_" . "{$document->getInternalId()}" . ".builds.storage")); - $buildsCompute = $dbForProject->getDocument('stats', md5("_inf_" . "{$document->getInternalId()}" . ".builds.compute")); - $executions = $dbForProject->getDocument('stats', md5("_inf_" . "{$document->getInternalId()}" . ".executions")); - $executionsCompute = $dbForProject->getDocument('stats', md5("_inf_" . "{$document->getInternalId()}" . ".executions.compute")); + $deployments = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['function', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); + $deploymentsStorage = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['function', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); + $builds = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); + $buildsStorage = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); + $buildsCompute = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); + $executions = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); + $executionsCompute = $dbForProject->getDocument('stats', md5(INFINITI_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); if (!empty($deployments['value'])) { $metrics[] = [ - 'key' => 'deployments', + 'key' => METRIC_DEPLOYMENTS, 'value' => ($deployments['value'] * -1), ]; } if (!empty($deploymentsStorage['value'])) { $metrics[] = [ - 'key' => 'deployments.storage', + 'key' => METRIC_DEPLOYMENTS_STORAGE, 'value' => ($deploymentsStorage['value'] * -1), ]; } if (!empty($builds['value'])) { $metrics[] = [ - 'key' => 'builds', + 'key' => METRIC_BUILDS, 'value' => ($builds['value'] * -1), ]; } if (!empty($buildsStorage['value'])) { $metrics[] = [ - 'key' => 'builds.storage', + 'key' => METRIC_BUILDS_STORAGE, 'value' => ($buildsStorage['value'] * -1), ]; } if (!empty($buildsCompute['value'])) { $metrics[] = [ - 'key' => 'builds.compute', + 'key' => METRIC_BUILDS_COMPUTE, 'value' => ($buildsCompute['value'] * -1), ]; } if (!empty($executions['value'])) { $metrics[] = [ - 'key' => 'executions', + 'key' => METRIC_EXECUTIONS, 'value' => ($executionsCompute['value'] * -1), ]; } if (!empty($executionsCompute['value'])) { $metrics[] = [ - 'key' => 'executions.compute', + 'key' => METRIC_EXECUTIONS_COMPUTE, 'value' => ($executionsCompute['value'] * -1), ]; } @@ -233,7 +235,7 @@ $server $dbForProject->setNamespace('_' . $projectInternalId); - foreach ($project['keys'] as $key => $value) { + foreach ($project['keys'] ?? [] as $key => $value) { if ($value == 0) { continue; } @@ -270,10 +272,12 @@ $server } } } - $dbForProject->createDocument('statsLogger', new Document([ - 'time' => DateTime::now(), - 'metrics' => $project['keys'], - ])); + if (!empty($project['keys'])) { + $dbForProject->createDocument('statsLogger', new Document([ + 'time' => DateTime::now(), + 'metrics' => $project['keys'], + ])); + } } catch (\Exception $e) { console::error("[logger] " . " {DateTime::now()} " . " {$projectInternalId} " . " {$e->getMessage()}"); } finally { diff --git a/bin/benchmark b/bin/benchmark deleted file mode 100644 index de9bee100c..0000000000 --- a/bin/benchmark +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env sh - -/usr/src/code/vendor/bin/phpbench run --config /usr/src/code/phpbench.json --report appwrite $@ \ No newline at end of file diff --git a/bin/executor b/bin/executor deleted file mode 100644 index f08bd68e42..0000000000 --- a/bin/executor +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -php -e /usr/src/code/app/executor.php -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php \ No newline at end of file diff --git a/composer.json b/composer.json index cc62e8e8a0..5cbdf064ed 100644 --- a/composer.json +++ b/composer.json @@ -12,19 +12,7 @@ "scripts": { "test": "vendor/bin/phpunit", "lint": "vendor/bin/phpcs", - "format": "vendor/bin/phpcbf", - "benchmark": [ - "Composer\\Config::disableProcessTimeout", - "vendor/bin/phpbench run --report=appwrite --" - ], - "benchmark-tag": [ - "Composer\\Config::disableProcessTimeout", - "vendor/bin/phpbench run --report=appwrite --tag=baseline --" - ], - "benchmark-compare": [ - "Composer\\Config::disableProcessTimeout", - "vendor/bin/phpbench run --report=appwrite --ref=baseline --" - ] + "format": "vendor/bin/phpcbf" }, "autoload": { "psr-4": { @@ -36,7 +24,6 @@ "psr-4": { "Tests\\E2E\\": "tests/e2e", "Tests\\Unit\\": "tests/unit", - "Tests\\Benchmarks\\": "tests/benchmarks", "Appwrite\\Tests\\": "tests/extensions" } }, @@ -76,7 +63,7 @@ "utopia-php/logger": "0.3.*", "utopia-php/messaging": "0.1.*", "utopia-php/registry": "0.5.*", - "utopia-php/storage": "0.13.0", + "utopia-php/storage": "0.13.*", "utopia-php/swoole": "0.5.*", "utopia-php/websocket": "0.1.0", "resque/php-resque": "1.3.6", @@ -100,14 +87,7 @@ "phpunit/phpunit": "9.5.20", "squizlabs/php_codesniffer": "^3.6", "swoole/ide-helper": "4.8.9", - "textalk/websocket": "1.5.7", - "phpbench/phpbench": "^1.2", - - "symfony/console": "^5.0", - "symfony/filesystem": "^5.0", - "symfony/finder": "^5.0", - "symfony/options-resolver": "^5.0", - "symfony/process": "^5.0" + "textalk/websocket": "1.5.7" }, "provide": { "ext-phpiredis": "*" diff --git a/composer.lock b/composer.lock index 107a8b09ea..84ff5b949e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "55eaba9ed1fd51ed74a18ee488c3fdd1", + "content-hash": "290f8f03716871b264f9dd88b0ef60a9", "packages": [ { "name": "adhocore/jwt", @@ -1736,12 +1736,12 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "fc0a8bfc9826e1e64521a8e7a95904f9a999d6fb" + "reference": "e548c4b5c6f1d7cfc9ba0113fbeb8c4684eddcd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/fc0a8bfc9826e1e64521a8e7a95904f9a999d6fb", - "reference": "fc0a8bfc9826e1e64521a8e7a95904f9a999d6fb", + "url": "https://api.github.com/repos/utopia-php/database/zipball/e548c4b5c6f1d7cfc9ba0113fbeb8c4684eddcd2", + "reference": "e548c4b5c6f1d7cfc9ba0113fbeb8c4684eddcd2", "shasum": "" }, "require": { @@ -1758,7 +1758,7 @@ "mongodb/mongodb": "1.8.0", "phpunit/phpunit": "^9.4", "swoole/ide-helper": "4.8.0", - "utopia-php/cli": "^0.11.0", + "utopia-php/cli": "^0.14.0", "vimeo/psalm": "4.0.1" }, "type": "library", @@ -1783,7 +1783,7 @@ "issues": "https://github.com/utopia-php/database/issues", "source": "https://github.com/utopia-php/database/tree/increment" }, - "time": "2022-12-08T08:59:37+00:00" + "time": "2023-02-05T10:33:42+00:00" }, { "name": "utopia-php/domains", @@ -3279,198 +3279,6 @@ }, "time": "2022-02-21T01:04:05+00:00" }, - { - "name": "phpbench/container", - "version": "2.2.1", - "source": { - "type": "git", - "url": "https://github.com/phpbench/container.git", - "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/container/zipball/6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", - "reference": "6d555ff7174fca13f9b1ec0b4a089ed41d0ab392", - "shasum": "" - }, - "require": { - "psr/container": "^1.0|^2.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", - "phpstan/phpstan": "^0.12.52", - "phpunit/phpunit": "^8" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\DependencyInjection\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "Simple, configurable, service container.", - "support": { - "issues": "https://github.com/phpbench/container/issues", - "source": "https://github.com/phpbench/container/tree/2.2.1" - }, - "time": "2022-01-25T10:17:35+00:00" - }, - { - "name": "phpbench/dom", - "version": "0.3.2", - "source": { - "type": "git", - "url": "https://github.com/phpbench/dom.git", - "reference": "b013b717832ddbaadf2a40984b04bc66af9a7110" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/dom/zipball/b013b717832ddbaadf2a40984b04bc66af9a7110", - "reference": "b013b717832ddbaadf2a40984b04bc66af9a7110", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "php": "^7.2||^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.18", - "phpstan/phpstan": "^0.12.83", - "phpunit/phpunit": "^8.0||^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "PhpBench\\Dom\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "DOM wrapper to simplify working with the PHP DOM implementation", - "support": { - "issues": "https://github.com/phpbench/dom/issues", - "source": "https://github.com/phpbench/dom/tree/0.3.2" - }, - "time": "2021-09-24T15:26:07+00:00" - }, - { - "name": "phpbench/phpbench", - "version": "1.2.8", - "source": { - "type": "git", - "url": "https://github.com/phpbench/phpbench.git", - "reference": "3f7b3c200f86727de7a14bde94adb68a88e1bafc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpbench/phpbench/zipball/3f7b3c200f86727de7a14bde94adb68a88e1bafc", - "reference": "3f7b3c200f86727de7a14bde94adb68a88e1bafc", - "shasum": "" - }, - "require": { - "doctrine/annotations": "^1.13 || ^2.0", - "ext-dom": "*", - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "ext-tokenizer": "*", - "php": "^7.3 || ^8.0", - "phpbench/container": "^2.1", - "phpbench/dom": "~0.3.1", - "psr/log": "^1.1 || ^2.0 || ^3.0", - "seld/jsonlint": "^1.1", - "symfony/console": "^4.2 || ^5.0 || ^6.0", - "symfony/filesystem": "^4.2 || ^5.0 || ^6.0", - "symfony/finder": "^4.2 || ^5.0 || ^6.0", - "symfony/options-resolver": "^4.2 || ^5.0 || ^6.0", - "symfony/process": "^4.2 || ^5.0 || ^6.0", - "webmozart/glob": "^4.6" - }, - "require-dev": { - "dantleech/invoke": "^2.0", - "friendsofphp/php-cs-fixer": "^3.0", - "jangregor/phpstan-prophecy": "^1.0", - "phpspec/prophecy": "^1.12", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5.8 || ^9.0", - "symfony/error-handler": "^5.2 || ^6.0", - "symfony/var-dumper": "^4.0 || ^5.0 || ^6.0" - }, - "suggest": { - "ext-xdebug": "For Xdebug profiling extension." - }, - "bin": [ - "bin/phpbench" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2-dev" - } - }, - "autoload": { - "files": [ - "lib/Report/Func/functions.php" - ], - "psr-4": { - "PhpBench\\": "lib/", - "PhpBench\\Extensions\\XDebug\\": "extensions/xdebug/lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Daniel Leech", - "email": "daniel@dantleech.com" - } - ], - "description": "PHP Benchmarking Framework", - "support": { - "issues": "https://github.com/phpbench/phpbench/issues", - "source": "https://github.com/phpbench/phpbench/tree/1.2.8" - }, - "funding": [ - { - "url": "https://github.com/dantleech", - "type": "github" - } - ], - "time": "2023-01-14T13:08:42+00:00" - }, { "name": "phpdocumentor/reflection-common", "version": "2.2.0", @@ -3638,20 +3446,20 @@ }, { "name": "phpspec/prophecy", - "version": "v1.16.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "be8cac52a0827776ff9ccda8c381ac5b71aeb359" + "reference": "15873c65b207b07765dbc3c95d20fdf4a320cbe2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be8cac52a0827776ff9ccda8c381ac5b71aeb359", - "reference": "be8cac52a0827776ff9ccda8c381ac5b71aeb359", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/15873c65b207b07765dbc3c95d20fdf4a320cbe2", + "reference": "15873c65b207b07765dbc3c95d20fdf4a320cbe2", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.2", + "doctrine/instantiator": "^1.2 || ^2.0", "php": "^7.2 || 8.0.* || 8.1.* || 8.2.*", "phpdocumentor/reflection-docblock": "^5.2", "sebastian/comparator": "^3.0 || ^4.0", @@ -3659,6 +3467,7 @@ }, "require-dev": { "phpspec/phpspec": "^6.0 || ^7.0", + "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^8.0 || ^9.0" }, "type": "library", @@ -3699,22 +3508,22 @@ ], "support": { "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.16.0" + "source": "https://github.com/phpspec/prophecy/tree/v1.17.0" }, - "time": "2022-11-29T15:06:56+00:00" + "time": "2023-02-02T15:41:36+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.23", + "version": "9.2.24", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c" + "reference": "2cf940ebc6355a9d430462811b5aaa308b174bed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c", - "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2cf940ebc6355a9d430462811b5aaa308b174bed", + "reference": "2cf940ebc6355a9d430462811b5aaa308b174bed", "shasum": "" }, "require": { @@ -3770,7 +3579,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.24" }, "funding": [ { @@ -3778,7 +3587,7 @@ "type": "github" } ], - "time": "2022-12-28T12:41:10+00:00" + "time": "2023-01-26T08:26:55+00:00" }, { "name": "phpunit/php-file-iterator", @@ -4124,108 +3933,6 @@ ], "time": "2022-04-01T12:37:26+00:00" }, - { - "name": "psr/cache", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", - "shasum": "" - }, - "require": { - "php": ">=8.0.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/3.0.0" - }, - "time": "2021-02-03T23:26:27+00:00" - }, - { - "name": "psr/container", - "version": "2.0.2", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" - }, - "time": "2021-11-05T16:47:00+00:00" - }, { "name": "sebastian/cli-parser", "version": "1.0.1", @@ -4592,16 +4299,16 @@ }, { "name": "sebastian/environment", - "version": "5.1.4", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -4643,7 +4350,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -4651,7 +4358,7 @@ "type": "github" } ], - "time": "2022-04-03T09:37:03+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", @@ -4965,16 +4672,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -5013,10 +4720,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -5024,7 +4731,7 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -5083,16 +4790,16 @@ }, { "name": "sebastian/type", - "version": "3.2.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { @@ -5127,7 +4834,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -5135,7 +4842,7 @@ "type": "github" } ], - "time": "2022-09-12T14:47:03+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -5190,70 +4897,6 @@ ], "time": "2020-09-28T06:39:44+00:00" }, - { - "name": "seld/jsonlint", - "version": "1.9.0", - "source": { - "type": "git", - "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "4211420d25eba80712bff236a98960ef68b866b7" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/4211420d25eba80712bff236a98960ef68b866b7", - "reference": "4211420d25eba80712bff236a98960ef68b866b7", - "shasum": "" - }, - "require": { - "php": "^5.3 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^1.5", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13" - }, - "bin": [ - "bin/jsonlint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Seld\\JsonLint\\": "src/Seld/JsonLint/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "JSON Linter", - "keywords": [ - "json", - "linter", - "parser", - "validator" - ], - "support": { - "issues": "https://github.com/Seldaek/jsonlint/issues", - "source": "https://github.com/Seldaek/jsonlint/tree/1.9.0" - }, - "funding": [ - { - "url": "https://github.com/Seldaek", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint", - "type": "tidelift" - } - ], - "time": "2022-04-01T13:37:23+00:00" - }, { "name": "squizlabs/php_codesniffer", "version": "3.7.1", @@ -5352,368 +4995,6 @@ ], "time": "2022-04-18T20:38:04+00:00" }, - { - "name": "symfony/console", - "version": "v5.4.17", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "58422fdcb0e715ed05b385f70d3e8b5ed4bbd45f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/58422fdcb0e715ed05b385f70d3e8b5ed4bbd45f", - "reference": "58422fdcb0e715ed05b385f70d3e8b5ed4bbd45f", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" - }, - "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0" - }, - "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Eases the creation of beautiful and testable command line interfaces", - "homepage": "https://symfony.com", - "keywords": [ - "cli", - "command line", - "console", - "terminal" - ], - "support": { - "source": "https://github.com/symfony/console/tree/v5.4.17" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-12-28T14:15:31+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v3.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3", - "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.3-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-25T10:21:52+00:00" - }, - { - "name": "symfony/filesystem", - "version": "v5.4.13", - "source": { - "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "ac09569844a9109a5966b9438fc29113ce77cf51" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/ac09569844a9109a5966b9438fc29113ce77cf51", - "reference": "ac09569844a9109a5966b9438fc29113ce77cf51", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides basic utilities for the filesystem", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.13" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-09-21T19:53:16+00:00" - }, - { - "name": "symfony/finder", - "version": "v5.4.17", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "40c08632019838dfb3350f18cf5563b8080055fc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/40c08632019838dfb3350f18cf5563b8080055fc", - "reference": "40c08632019838dfb3350f18cf5563b8080055fc", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.17" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-12-22T10:31:03+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v5.4.11", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/54f14e36aa73cb8f7261d7686691fd4d75ea2690", - "reference": "54f14e36aa73cb8f7261d7686691fd4d75ea2690", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-07-20T13:00:38+00:00" - }, { "name": "symfony/polyfill-ctype", "version": "v1.27.0", @@ -5796,171 +5077,6 @@ ], "time": "2022-11-03T14:55:06+00:00" }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's Normalizer class and related functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "intl", - "normalizer", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, { "name": "symfony/polyfill-mbstring", "version": "v1.27.0", @@ -6044,318 +5160,6 @@ ], "time": "2022-11-03T14:55:06+00:00" }, - { - "name": "symfony/polyfill-php73", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/process", - "version": "v5.4.11", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/6e75fe6874cbc7e4773d049616ab450eff537bf1", - "reference": "6e75fe6874cbc7e4773d049616ab450eff537bf1", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v5.4.11" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-06-27T16:58:25+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v3.2.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/aac98028c69df04ee77eb69b96b86ee51fbf4b75", - "reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^2.0" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.3-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to writing services", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.2.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-25T10:21:52+00:00" - }, - { - "name": "symfony/string", - "version": "v6.2.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "863219fd713fa41cbcd285a79723f94672faff4d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/863219fd713fa41cbcd285a79723f94672faff4d", - "reference": "863219fd713fa41cbcd285a79723f94672faff4d", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.0" - }, - "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/intl": "^6.2", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", - "homepage": "https://symfony.com", - "keywords": [ - "grapheme", - "i18n", - "string", - "unicode", - "utf-8", - "utf8" - ], - "support": { - "source": "https://github.com/symfony/string/tree/v6.2.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-12-14T16:11:27+00:00" - }, { "name": "textalk/websocket", "version": "1.5.7", @@ -6532,6 +5336,14 @@ "time": "2022-12-27T12:28:18+00:00" } ], + "aliases": [ + { + "package": "utopia-php/database", + "version": "dev-increment", + "alias": "0.28.0", + "alias_normalized": "0.28.0.0" + } + ], "minimum-stability": "stable", "stability-flags": { "utopia-php/database": 20 diff --git a/docker-compose.yml b/docker-compose.yml index 89d3c155dd..7e61a3f1fb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,15 +33,6 @@ services: - 8080:80 - 443:443 - 9500:8080 - ulimits: - nofile: - soft: 655350 - hard: 655350 - sysctls: - - net.core.somaxconn=1024 - - net.ipv4.tcp_rmem=1024 4096 16384 - - net.ipv4.tcp_wmem=1024 4096 16384 - - net.ipv4.ip_local_port_range=1025 65535 volumes: - /var/run/docker.sock:/var/run/docker.sock - appwrite-config:/storage/config:ro @@ -62,6 +53,7 @@ services: DEBUG: false TESTING: true VERSION: dev + VITE_CONSOLE_MODE: self-hosted ports: - 9501:80 networks: @@ -93,6 +85,7 @@ services: - ./public:/usr/src/code/public - ./src:/usr/src/code/src - ./dev:/usr/local/dev + depends_on: - mariadb - redis @@ -342,7 +335,6 @@ services: volumes: - ./app:/usr/src/code/app - ./src:/usr/src/code/src - #- ./vendor/utopia-php/database:/usr/src/code/vendor/utopia-php/database depends_on: - redis - mariadb @@ -548,6 +540,45 @@ services: - _APP_LOGGING_PROVIDER - _APP_LOGGING_CONFIG + appwrite-maintenance: + entrypoint: maintenance + <<: *x-logging + container_name: appwrite-maintenance + image: appwrite-dev + networks: + - appwrite + volumes: + - ./app:/usr/src/code/app + - ./src:/usr/src/code/src + depends_on: + - redis + environment: + - _APP_ENV + - _APP_WORKER_PER_CORE + - _APP_CONNECTIONS_MAX + - _APP_POOL_CLIENTS + - _APP_DOMAIN + - _APP_DOMAIN_TARGET + - _APP_OPENSSL_KEY_V1 + - _APP_DB_HOST + - _APP_DB_PORT + - _APP_DB_SCHEMA + - _APP_DB_USER + - _APP_DB_PASS + - _APP_REDIS_HOST + - _APP_REDIS_PORT + - _APP_REDIS_USER + - _APP_REDIS_PASS + - _APP_CONNECTIONS_DB_CONSOLE + - _APP_CONNECTIONS_DB_PROJECT + - _APP_CONNECTIONS_CACHE + - _APP_MAINTENANCE_INTERVAL + - _APP_MAINTENANCE_RETENTION_EXECUTION + - _APP_MAINTENANCE_RETENTION_CACHE + - _APP_MAINTENANCE_RETENTION_ABUSE + - _APP_MAINTENANCE_RETENTION_AUDIT + - _APP_MAINTENANCE_RETENTION_SCHEDULES + appwrite-worker-usage: entrypoint: worker-usage <<: *x-logging @@ -558,7 +589,6 @@ services: volumes: - ./app:/usr/src/code/app - ./src:/usr/src/code/src - #- ./vendor/utopia-php/database:/usr/src/code/vendor/utopia-php/database depends_on: - redis - mariadb @@ -585,43 +615,6 @@ services: - DOCKERHUB_PULL_USERNAME - DOCKERHUB_PULL_PASSWORD - appwrite-maintenance: - entrypoint: maintenance - <<: *x-logging - container_name: appwrite-maintenance - image: appwrite-dev - networks: - - appwrite - volumes: - - ./app:/usr/src/code/app - - ./src:/usr/src/code/src - depends_on: - - redis - environment: - - _APP_ENV - - _APP_WORKER_PER_CORE - - _APP_DOMAIN - - _APP_DOMAIN_TARGET - - _APP_OPENSSL_KEY_V1 - - _APP_DB_HOST - - _APP_DB_PORT - - _APP_DB_SCHEMA - - _APP_DB_USER - - _APP_DB_PASS - - _APP_REDIS_HOST - - _APP_REDIS_PORT - - _APP_REDIS_USER - - _APP_REDIS_PASS - - _APP_CONNECTIONS_DB_CONSOLE - - _APP_CONNECTIONS_DB_PROJECT - - _APP_CONNECTIONS_CACHE - - _APP_MAINTENANCE_INTERVAL - - _APP_MAINTENANCE_RETENTION_EXECUTION - - _APP_MAINTENANCE_RETENTION_CACHE - - _APP_MAINTENANCE_RETENTION_ABUSE - - _APP_MAINTENANCE_RETENTION_AUDIT - - _APP_MAINTENANCE_RETENTION_SCHEDULES - appwrite-schedule: entrypoint: schedule <<: *x-logging @@ -663,7 +656,7 @@ services: image: openruntimes/executor:0.1.6 networks: - appwrite - - openruntimes-runtimes + - runtimes volumes: - /var/run/docker.sock:/var/run/docker.sock - appwrite-builds:/storage/builds:rw @@ -819,8 +812,8 @@ networks: name: gateway appwrite: name: appwrite - openruntimes-runtimes: - name: openruntimes-runtimes + runtimes: + name: runtimes volumes: appwrite-mariadb: diff --git a/docs/specs/overview.drawio.svg b/docs/specs/overview.drawio.svg index 2eb08f2b3d..d888a2cfcf 100644 --- a/docs/specs/overview.drawio.svg +++ b/docs/specs/overview.drawio.svg @@ -1,880 +1,4 @@ - - - - - - - - - -
-
-
- Web -
-
-
-
- - Web - -
-
- - - - - - -
-
-
- Flutter -
-
-
-
- - Flutter - -
-
- - - - - - -
-
-
- iOS -
-
-
-
- - iOS - -
-
- - - - - - -
-
-
- Android -
-
-
-
- - Android - -
-
- - - - - - -
-
-
- Servers -
-
-
-
- - Servers - -
-
- - - - - - -
-
-
- Appwrite -
-
-
-
- - Appwrite - -
-
- - - - - - - - - - - - - - -
-
-
- Loadbalancer -
-
-
-
- - Loadbalancer - -
-
- - - - - - - - - - - - - - - - - - - - - - -
-
-
- REST API -
-
-
-
- - REST API - -
-
- - - - -
-
-
- Queue -
- - (Redis) - -
-
-
-
- - Queue... - -
-
- - - - - - - - -
-
-
- Cache -
- - (Redis) - -
-
-
-
- - Cache... - -
-
- - - - -
-
-
- Database -
-
-
-
- - Database - -
-
- - - - -
-
-
- Users -
-
-
-
- - Users - -
-
- - - - -
-
-
- Account -
-
-
-
- - Account - -
-
- - - - -
-
-
- Teams -
-
-
-
- - Teams - -
-
- - - - -
-
-
- Database -
-
-
-
- - Database - -
-
- - - - -
-
-
- Storage -
-
-
-
- - Storage - -
-
- - - - -
-
-
- Localization -
-
-
-
- - Localization - -
-
- - - - -
-
-
- Avatars -
-
-
-
- - Avatars - -
-
- - - - -
-
-
- Health -
-
-
-
- - Health - -
-
- - - - -
-
-
- SSL Gateway -
-
-
-
- - SSL Gateway - -
-
- - - - - - -
-
-
- Maintenance -
-
-
-
- - Maintenance - -
-
- - - - - - - - - - - - - -
-
-
- Security Layer -
-
-
-
- - Security Layer - -
-
- - - - - - - - - - -
-
-
- Usage -
-
-
-
- - Usage - -
-
- - - - - - - - -
-
-
- Audits -
-
-
-
- - Audits - -
-
- - - - - - - - -
-
-
- Mails -
-
-
-
- - Mails - -
-
- - - - -
-
-
- SMTP -
-
-
-
- - SMTP - -
-
- - - - - - - - -
-
-
- Database -
-
-
-
- - Database - -
-
- - - - - - - - -
-
-
- Webhooks -
-
-
-
- - Webhooks - -
-
- - - - - - - - - - - -
-
-
- Functions -
-
-
-
- - Functions - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- Certs -
-
-
-
- - Certs - -
-
- - - - - - -
-
-
- Deletes -
-
-
-
- - Deletes - -
-
- - - - - - -
-
-
- Letsencrypt -
-
-
-
- - Letsencrypt - -
-
- - - - -
-
-
- AntiVirus -
- - (ClamAV) - -
-
-
-
- - AntiVirus... - -
-
- - - - - - - - -
-
-
- Realtime API -
-
-
-
- - Realtime API - -
-
- - - - -
-
-
- Scheduler -
-
-
-
- - Scheduler - -
-
- - - - -
-
-
- Builds -
-
-
-
- - Builds - -
-
- - - - - - - - - - -
-
-
- Executor -
- - (Open-Runtimes) - -
-
-
-
- - Executor... - -
-
- - - - -
-
-
- Docker / K8S -
-
-
-
- - Docker / K8S - -
-
- - - - -
-
-
- Console -
-
-
-
- - Console - -
-
- - - - -
-
-
- Functions -
-
-
-
- - Functions - -
-
- - - - - - -
-
-
- GraphQL API -
- - (Coming Soon) - -
-
-
-
- - GraphQL API... - -
-
-
- - - - - Viewer does not support full SVG 1.1 - - - -
\ No newline at end of file + + + +
Web
Web
Flutter
Flutter
iOS
iOS
Android
Android
Servers
Servers
Appwrite
Appwrite
Loadbalancer
Loadbalancer
REST API
REST API
Queue
(Redis)
Queue...
Cache
(Redis)
Cache...
Database
Database
Users
Users
Account
Account
Teams
Teams
Database
Database
Storage
Storage
Localization
Localization
Avatars
Avatars
Health
Health
SSL Gateway
SSL Gateway
Maintenance
Maintenance
Security Layer
Security Layer
Usage
Usage
Audits
Audits
Mails
Mails
SMTP
SMTP
Database
Database
Webhooks
Webhooks
Functions
Functions
Certs
Certs
Deletes
Deletes
Letsencrypt
Letsencrypt
AntiVirus
(ClamAV)
AntiVirus...
Realtime API
Realtime API
Scheduler
Scheduler
Builds
Builds
Executor
(Open-Runtimes)
Executor...
Docker / K8S
Docker / K8S
Console
Console
Functions
Functions
GraphQL API
(Coming Soon)
GraphQL API...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/docs/tutorials/add-route.md b/docs/tutorials/add-route.md index f66276e973..52f0cb4c0a 100644 --- a/docs/tutorials/add-route.md +++ b/docs/tutorials/add-route.md @@ -127,11 +127,6 @@ App::post('/v1/storage/buckets/:bucketId/files') ->label('event', 'buckets.[bucketId].files.[fileId].create') ``` -#### Usage - -- usage.metric - The metric the route generates. -- usage.params - Additional parameters the metrics can have. - ```php App::post('/v1/storage/buckets/:bucketId/files') ->label('usage.metric', 'files.{scope}.requests.create') diff --git a/phpbench.json b/phpbench.json deleted file mode 100644 index 4ebdc080b4..0000000000 --- a/phpbench.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "./vendor/phpbench/phpbench/phpbench.schema.json", - "runner.path": "tests/benchmarks", - "runner.file_pattern": "*Bench.php", - "runner.bootstrap": "app/init.php", - "runner.revs": 1000, - "runner.iterations": 3, - "runner.retry_threshold": 5, - "runner.warmup": 1, - "report.generators": { - "appwrite": { - "extends": "aggregate", - "cols": ["benchmark", "subject", "set" ,"revs", "its", "worst", "best", "mean", "mode", "rstdev"], - "break": ["benchmark"] - } - } -} \ No newline at end of file diff --git a/src/Appwrite/Auth/Auth.php b/src/Appwrite/Auth/Auth.php index b397e9ea77..63b6a254f0 100644 --- a/src/Appwrite/Auth/Auth.php +++ b/src/Appwrite/Auth/Auth.php @@ -9,10 +9,9 @@ use Appwrite\Auth\Hash\Phpass; use Appwrite\Auth\Hash\Scrypt; use Appwrite\Auth\Hash\Scryptmodified; use Appwrite\Auth\Hash\Sha; -use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\DateTime; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Roles; diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index dddbc59e7f..435972d0f5 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -6,8 +6,8 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Appwrite\Messaging\Adapter; use Utopia\App; -use Utopia\Database\ID; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Role; class Realtime extends Adapter { diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index a0c237fd5f..251e72fe66 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -10,7 +10,7 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Exception; use Utopia\App; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; Runtime::enableCoroutine(SWOOLE_HOOK_ALL); diff --git a/src/Appwrite/Migration/Version/V15.php b/src/Appwrite/Migration/Version/V15.php index f549c7fbdf..ac948d01d2 100644 --- a/src/Appwrite/Migration/Version/V15.php +++ b/src/Appwrite/Migration/Version/V15.php @@ -11,9 +11,9 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class V15 extends Migration { diff --git a/src/Appwrite/Platform/Services/Tasks.php b/src/Appwrite/Platform/Services/Tasks.php index f28dd82e4d..6371a8e24e 100644 --- a/src/Appwrite/Platform/Services/Tasks.php +++ b/src/Appwrite/Platform/Services/Tasks.php @@ -13,7 +13,6 @@ use Appwrite\Platform\Tasks\SDKs; use Appwrite\Platform\Tasks\Specs; use Appwrite\Platform\Tasks\SSL; use Appwrite\Platform\Tasks\Hamster; -use Appwrite\Platform\Tasks\Usage; use Appwrite\Platform\Tasks\Vars; use Appwrite\Platform\Tasks\Version; use Appwrite\Platform\Tasks\VolumeSync; diff --git a/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php b/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php index 32b9886347..74ef644498 100644 --- a/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php +++ b/src/Appwrite/Platform/Tasks/PatchCreateMissingSchedules.php @@ -8,7 +8,7 @@ use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Database\Database; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; class PatchCreateMissingSchedules extends Action diff --git a/src/Appwrite/Specification/Format/OpenAPI3.php b/src/Appwrite/Specification/Format/OpenAPI3.php index fb7208c569..1ad5dfd895 100644 --- a/src/Appwrite/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/Specification/Format/OpenAPI3.php @@ -5,8 +5,8 @@ namespace Appwrite\Specification\Format; use Appwrite\Specification\Format; use Appwrite\Template\Template; use Appwrite\Utopia\Response\Model; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; use Utopia\Validator; class OpenAPI3 extends Format diff --git a/src/Appwrite/Specification/Format/Swagger2.php b/src/Appwrite/Specification/Format/Swagger2.php index 6eb27a11aa..7d056bea60 100644 --- a/src/Appwrite/Specification/Format/Swagger2.php +++ b/src/Appwrite/Specification/Format/Swagger2.php @@ -5,8 +5,8 @@ namespace Appwrite\Specification\Format; use Appwrite\Specification\Format; use Appwrite\Template\Template; use Appwrite\Utopia\Response\Model; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; use Utopia\Validator; class Swagger2 extends Format diff --git a/src/Appwrite/Utopia/Request/Filters/V15.php b/src/Appwrite/Utopia/Request/Filters/V15.php index 65b09e1f24..50e5ec0db7 100644 --- a/src/Appwrite/Utopia/Request/Filters/V15.php +++ b/src/Appwrite/Utopia/Request/Filters/V15.php @@ -4,9 +4,9 @@ namespace Appwrite\Utopia\Request\Filters; use Appwrite\Utopia\Request\Filter; use Utopia\Database\Database; -use Utopia\Database\Permission; +use Utopia\Database\Helpers\Permission; use Utopia\Database\Query; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Role; class V15 extends Filter { diff --git a/src/Appwrite/Utopia/Response/Filters/V15.php b/src/Appwrite/Utopia/Response/Filters/V15.php index a74f0f32ad..232feec201 100644 --- a/src/Appwrite/Utopia/Response/Filters/V15.php +++ b/src/Appwrite/Utopia/Response/Filters/V15.php @@ -5,8 +5,8 @@ namespace Appwrite\Utopia\Response\Filters; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Filter; use Utopia\Database\Database; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class V15 extends Filter { diff --git a/src/Appwrite/Utopia/Response/Model/Execution.php b/src/Appwrite/Utopia/Response/Model/Execution.php index 13011a24b7..8672a91598 100644 --- a/src/Appwrite/Utopia/Response/Model/Execution.php +++ b/src/Appwrite/Utopia/Response/Model/Execution.php @@ -4,7 +4,7 @@ namespace Appwrite\Utopia\Response\Model; use Appwrite\Utopia\Response; use Appwrite\Utopia\Response\Model; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Role; class Execution extends Model { diff --git a/src/Appwrite/Utopia/Response/Model/UsageBuckets.php b/src/Appwrite/Utopia/Response/Model/UsageBuckets.php index 40d5c6c4a6..83b8744760 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageBuckets.php +++ b/src/Appwrite/Utopia/Response/Model/UsageBuckets.php @@ -16,7 +16,7 @@ class UsageBuckets extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('filesCount', [ + ->addRule('filesTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of files in this bucket.', 'default' => [], diff --git a/src/Appwrite/Utopia/Response/Model/UsageCollection.php b/src/Appwrite/Utopia/Response/Model/UsageCollection.php index 1f60076d02..5abcf46b7d 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageCollection.php +++ b/src/Appwrite/Utopia/Response/Model/UsageCollection.php @@ -16,7 +16,7 @@ class UsageCollection extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('documentsCount', [ + ->addRule('documentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of documents.', 'default' => [], diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php index 7f3aab29aa..58d49c506e 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabase.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabase.php @@ -16,14 +16,14 @@ class UsageDatabase extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('collectionsCount', [ + ->addRule('collectionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of collections.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('documentsCount', [ + ->addRule('documentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of documents.', 'default' => [], diff --git a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php index a37639c28e..a6008ca9e6 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageDatabases.php +++ b/src/Appwrite/Utopia/Response/Model/UsageDatabases.php @@ -16,21 +16,21 @@ class UsageDatabases extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('databasesCount', [ + ->addRule('databasesTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of documents.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('collectionsCount', [ + ->addRule('collectionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of collections.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('documentsCount', [ + ->addRule('documentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of documents.', 'default' => [], diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunction.php b/src/Appwrite/Utopia/Response/Model/UsageFunction.php index f528a3c0b4..03acaa750a 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunction.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunction.php @@ -16,7 +16,7 @@ class UsageFunction extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('deployments', [ + ->addRule('deploymentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function deployments.', 'default' => [], @@ -30,7 +30,7 @@ class UsageFunction extends Model 'example' => [], 'array' => true ]) - ->addRule('builds', [ + ->addRule('buildsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function builds.', 'default' => [], @@ -44,14 +44,14 @@ class UsageFunction extends Model 'example' => [], 'array' => true ]) - ->addRule('buildsCompute', [ + ->addRule('buildsTime', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function build compute.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('executions', [ + ->addRule('executionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function executions.', 'default' => [], @@ -59,7 +59,7 @@ class UsageFunction extends Model 'array' => true ]) - ->addRule('executionsCompute', [ + ->addRule('executionsTime', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function execution compute.', 'default' => [], diff --git a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php index 585eceb1ea..6ab36e21ac 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageFunctions.php +++ b/src/Appwrite/Utopia/Response/Model/UsageFunctions.php @@ -16,14 +16,14 @@ class UsageFunctions extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('functions', [ + ->addRule('functionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of functions.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('deployments', [ + ->addRule('deploymentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function deployments.', 'default' => [], @@ -37,7 +37,7 @@ class UsageFunctions extends Model 'example' => [], 'array' => true ]) - ->addRule('builds', [ + ->addRule('buildsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function builds.', 'default' => [], @@ -51,14 +51,14 @@ class UsageFunctions extends Model 'example' => [], 'array' => true ]) - ->addRule('buildsCompute', [ + ->addRule('buildsTime', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function build compute.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('executions', [ + ->addRule('executionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of function executions.', 'default' => [], @@ -66,7 +66,7 @@ class UsageFunctions extends Model 'array' => true ]) - ->addRule('executionsCompute', [ + ->addRule('executionsTime', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function execution compute.', 'default' => [], diff --git a/src/Appwrite/Utopia/Response/Model/UsageProject.php b/src/Appwrite/Utopia/Response/Model/UsageProject.php index e37bc5928d..641613809a 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageProject.php +++ b/src/Appwrite/Utopia/Response/Model/UsageProject.php @@ -16,7 +16,7 @@ class UsageProject extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('requests', [ + ->addRule('requestsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of requests.', 'default' => [], @@ -30,42 +30,42 @@ class UsageProject extends Model 'example' => [], 'array' => true ]) - ->addRule('executions', [ + ->addRule('executionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for function executions.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('documents', [ + ->addRule('documentsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of documents.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('databases', [ + ->addRule('databasesTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of databases.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('users', [ + ->addRule('usersTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of users.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('storage', [ + ->addRule('filesStorage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for the occupied storage size (in bytes).', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('buckets', [ + ->addRule('bucketsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for number of buckets.', 'default' => [], diff --git a/src/Appwrite/Utopia/Response/Model/UsageStorage.php b/src/Appwrite/Utopia/Response/Model/UsageStorage.php index fe2f605677..30e181e7cc 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageStorage.php +++ b/src/Appwrite/Utopia/Response/Model/UsageStorage.php @@ -16,21 +16,21 @@ class UsageStorage extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('bucketsCount', [ + ->addRule('bucketsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of buckets.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('filesCount', [ + ->addRule('filesTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of files.', 'default' => [], 'example' => [], 'array' => true ]) - ->addRule('filesStorage', [ + ->addRule('storage', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for the occupied storage size (in bytes).', 'default' => [], diff --git a/src/Appwrite/Utopia/Response/Model/UsageUsers.php b/src/Appwrite/Utopia/Response/Model/UsageUsers.php index 335cb351a5..c0cc4baa54 100644 --- a/src/Appwrite/Utopia/Response/Model/UsageUsers.php +++ b/src/Appwrite/Utopia/Response/Model/UsageUsers.php @@ -16,7 +16,7 @@ class UsageUsers extends Model 'default' => '', 'example' => '30d', ]) - ->addRule('usersCount', [ + ->addRule('usersTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for total number of users.', 'default' => [], @@ -24,7 +24,7 @@ class UsageUsers extends Model 'array' => true ]) - ->addRule('sessionsCount', [ + ->addRule('sessionsTotal', [ 'type' => Response::MODEL_METRIC, 'description' => 'Aggregated stats for sessions created.', 'default' => [], diff --git a/tests/benchmarks/Scopes/Scope.php b/tests/benchmarks/Scopes/Scope.php deleted file mode 100644 index 03b2d7f1ef..0000000000 --- a/tests/benchmarks/Scopes/Scope.php +++ /dev/null @@ -1,14 +0,0 @@ -client->call(Client::METHOD_POST, '/databases/' . static::$databaseId . '/collections/' . static::$collectionId . '/documents', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'documentId' => ID::unique(), - 'data' => [ - 'title' => 'The Matrix', - ], - 'permissions' => [ - Permission::read(Role::user($this->getUser()['$id'])), - Permission::write(Role::user($this->getUser()['$id'])), - ], - ]); - } - - #[ParamProviders(['provideCounts'])] - #[BeforeMethods(['createDatabase', 'createCollection', 'createDocuments'])] - public function benchDocumentReadList(array $params) - { - $this->client->call(Client::METHOD_GET, '/databases/' . static::$databaseId . '/collections/' . static::$collectionId . '/documents', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => ['limit(' . $params['documents'] . ')'], - ]); - } - - #[BeforeMethods(['createDatabase', 'createCollection', 'createDocuments'])] - public function benchDocumentRead() - { - $this->client->call(Client::METHOD_GET, '/databases/' . static::$databaseId . '/collections/' . static::$collectionId . '/documents/' . static::$documentId, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - } - - #[BeforeMethods(['createDatabase', 'createCollection', 'createDocuments'])] - public function benchDocumentUpdate() - { - $this->client->call(Client::METHOD_PATCH, '/databases/' . static::$databaseId . '/collections/' . static::$collectionId . '/documents/' . static::$documentId, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'data' => [ - 'title' => 'The Matrix Reloaded', - ], - ]); - } - - public function provideCounts(): array - { - return [ - '1 Document' => ['documents' => 1], - '10 Documents' => ['documents' => 10], - '100 Documents' => ['documents' => 100], - ]; - } - - public function createDatabase(array $params = []) - { - $database = $this->client->call(Client::METHOD_POST, '/databases', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ], [ - 'databaseId' => ID::unique(), - 'name' => 'Test Database' - ]); - static::$databaseId = $database['body']['$id']; - } - - public function createCollection(array $params = []) - { - $collection = $this->client->call(Client::METHOD_POST, '/databases/' . static::$databaseId . '/collections', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ], [ - 'collectionId' => ID::unique(), - 'name' => 'Movies', - 'documentSecurity' => true, - 'permissions' => [ - Permission::read(Role::user($this->getUser()['$id'])), - Permission::write(Role::user($this->getUser()['$id'])), - ], - ]); - static::$collectionId = $collection['body']['$id']; - - // Create attribute - $this->client->call(Client::METHOD_POST, '/databases/' . static::$databaseId . '/collections/' . static::$collectionId . '/attributes/string', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ], [ - 'key' => 'title', - 'size' => 256, - 'required' => true, - ]); - - // Wait for attribute to be ready - sleep(2); - } - - public function createDocuments(array $params = []) - { - $count = $params['documents'] ?? 1; - - for ($i = 0; $i < $count; $i++) { - $response = $this->client->call(Client::METHOD_POST, '/databases/' . static::$databaseId . '/collections/' . static::$collectionId . '/documents', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ], [ - 'documentId' => ID::unique(), - 'data' => [ - 'title' => 'Captain America' . $i, - ], - 'permissions' => [ - Permission::read(Role::user($this->getUser()['$id'])), - Permission::write(Role::user($this->getUser()['$id'])), - ] - ]); - - static::$documentId = $response['body']['$id']; - } - } -} diff --git a/tests/benchmarks/Services/Databases/DatabasesCustomClientBench.php b/tests/benchmarks/Services/Databases/DatabasesCustomClientBench.php deleted file mode 100644 index 658ddfd98c..0000000000 --- a/tests/benchmarks/Services/Databases/DatabasesCustomClientBench.php +++ /dev/null @@ -1,10 +0,0 @@ -client->call(Client::METHOD_POST, '/functions/' . static::$functionId . '/executions', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - } - - public function createFunction() - { - $response = $this->client->call(Client::METHOD_POST, '/functions', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ], [ - 'functionId' => ID::unique(), - 'name' => 'Test', - 'runtime' => 'php-8.0', - 'timeout' => 10, - 'execute' => [Role::users()->toString()] - ]); - static::$functionId = $response['body']['$id']; - } - - public function prepareDeployment() - { - $stdout = ''; - $stderr = ''; - - Console::execute( - 'cd ' . realpath(__DIR__ . "/../../../resources/functions/php") . " && \ - tar --exclude code.tar.gz -czf code.tar.gz .", - '', - $stdout, - $stderr - ); - } - - public function createDeployment() - { - $code = realpath(__DIR__ . '/../../../resources/functions/php/code.tar.gz'); - - $response = $this->client->call(Client::METHOD_POST, '/functions/' . static::$functionId . '/deployments', [ - 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ], [ - 'entrypoint' => 'index.php', - 'code' => new CURLFile( - $code, - 'application/x-gzip', - \basename($code) - ), - ]); - - static::$deploymentId = $response['body']['$id']; - - while (true) { - $response = $this->client->call(Client::METHOD_GET, '/functions/' . static::$functionId . '/deployments/' . static::$deploymentId, [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ]); - - $status = $response['body']['status'] ?? ''; - - switch ($status) { - case '': - case 'processing': - case 'building': - usleep(200); - break; - case 'ready': - break 2; - case 'failed': - throw new \Exception('Failed to build function'); - } - } - - sleep(1); - } - - public function patchDeployment() - { - $this->client->call(Client::METHOD_PATCH, '/functions/' . static::$functionId . '/deployments/' . static::$deploymentId, [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ], []); - } -} diff --git a/tests/benchmarks/Services/Functions/FunctionsCustomClientBench.php b/tests/benchmarks/Services/Functions/FunctionsCustomClientBench.php deleted file mode 100644 index ec5e0b8f29..0000000000 --- a/tests/benchmarks/Services/Functions/FunctionsCustomClientBench.php +++ /dev/null @@ -1,10 +0,0 @@ -createDeployment(); - } -} diff --git a/tests/benchmarks/Services/Storage/Base.php b/tests/benchmarks/Services/Storage/Base.php deleted file mode 100644 index 6496490a6f..0000000000 --- a/tests/benchmarks/Services/Storage/Base.php +++ /dev/null @@ -1,117 +0,0 @@ -client->call(Client::METHOD_POST, '/storage/buckets/' . static::$bucketId . '/files', array_merge([ - 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'fileId' => ID::unique(), - 'permissions' => [ - Permission::read(Role::user($this->getUser()['$id'])), - Permission::write(Role::user($this->getUser()['$id'])), - ], - - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), - ]); - } - - #[ParamProviders(['provideCounts'])] - #[BeforeMethods(['createBucket', 'createFiles'])] - public function benchFileReadList(array $params) - { - $this->client->call(Client::METHOD_GET, '/storage/buckets/' . static::$bucketId . '/files', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => ['limit(' . $params['files'] . ')'], - ]); - } - - #[BeforeMethods(['createBucket', 'createFiles'])] - public function benchFileRead() - { - $this->client->call(Client::METHOD_GET, '/storage/buckets/' . static::$bucketId . '/files/' . static::$fileId, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - } - - #[BeforeMethods(['createBucket', 'createFiles'])] - public function benchFileUpdate() - { - $this->client->call(Client::METHOD_PUT, '/storage/buckets/' . static::$bucketId . '/files/' . static::$fileId, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'name' => 'Updated name', - 'permissions' => [], - ]); - } - - public function provideCounts(): array - { - return [ - '10 Files' => ['files' => 10], - '100 Files' => ['files' => 100], - ]; - } - - public function createBucket(array $params = []) - { - // Create bucket - $bucket = $this->client->call(Client::METHOD_POST, '/storage/buckets', [ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ], [ - 'bucketId' => ID::unique(), - 'name' => 'Test Bucket', - 'permissions' => [ - Permission::read(Role::user($this->getUser()['$id'])), - Permission::write(Role::user($this->getUser()['$id'])), - ], - 'fileSecurity' => true - ]); - static::$bucketId = $bucket['body']['$id']; - } - - public function createFiles(array $params = []) - { - $count = $params['files'] ?? 1; - - // Create files - for ($i = 0; $i < $count; $i++) { - $response = $this->client->call(Client::METHOD_POST, '/storage/buckets/' . static::$bucketId . '/files', [ - 'content-type' => 'multipart/form-data', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ], [ - 'fileId' => ID::unique(), - 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), - ]); - - static::$fileId = $response['body']['$id']; - } - } -} diff --git a/tests/benchmarks/Services/Storage/StorageCustomClientBench.php b/tests/benchmarks/Services/Storage/StorageCustomClientBench.php deleted file mode 100644 index 585182c1da..0000000000 --- a/tests/benchmarks/Services/Storage/StorageCustomClientBench.php +++ /dev/null @@ -1,10 +0,0 @@ -client->call(Client::METHOD_POST, '/users', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'userId' => $id, - 'email' => 'test' . $id . '@example.com', - 'password' => 'password', - ]); - } - - #[ParamProviders(['provideCounts'])] - #[BeforeMethods(['createUsers'])] - public function benchUserReadList(array $params) - { - $this->client->call(Client::METHOD_GET, '/users', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => ['limit(' . $params['users'] . ')'], - ]); - } - - #[BeforeMethods(['createUsers'])] - public function benchUserRead() - { - $this->client->call(Client::METHOD_GET, '/users/' . static::$userId, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - } - - #[BeforeMethods(['createUsers'])] - public function benchUserUpdate() - { - $this->client->call(Client::METHOD_PUT, '/users/' . static::$userId, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'name' => 'New Name', - ]); - } - - public function createUsers(array $params = []) - { - $count = $params['documents'] ?? 1; - - for ($i = 0; $i < $count; $i++) { - $id = ID::unique(); - - $response = $this->client->call(Client::METHOD_POST, '/users', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'userId' => $id, - 'email' => 'test' . $id . '@example.com', - 'password' => 'password', - ]); - - static::$userId = $response['body']['$id']; - } - } - - public function provideCounts(): array - { - return [ - '1 User' => ['users' => 1], - '10 Users' => ['users' => 10], - '100 Users' => ['users' => 100], - ]; - } -} diff --git a/tests/benchmarks/http.js b/tests/benchmarks/http.js new file mode 100644 index 0000000000..799c8fb23c --- /dev/null +++ b/tests/benchmarks/http.js @@ -0,0 +1,34 @@ +import http from 'k6/http'; +import { check } from 'k6'; +import { Counter } from 'k6/metrics'; + +// A simple counter for http requests +export const requests = new Counter('http_reqs'); + +// you can specify stages of your test (ramp up/down patterns) through the options object +// target is the number of VUs you are aiming for + +export const options = { + stages: [ + { target: 50, duration: '1m' }, + // { target: 15, duration: '1m' }, + // { target: 0, duration: '1m' }, + ], + thresholds: { + requests: ['count < 100'], + }, +}; + +export default function () { + const config = { + headers: { + 'X-Appwrite-Key': '24356eb021863f81eb7dd77c7750304d0464e141cad6e9a8befa1f7d2b066fde190df3dab1e8d2639dbb82ee848da30501424923f4cd80d887ee40ad77ded62763ee489448523f6e39667f290f9a54b2ab8fad131a0bc985e6c0f760015f7f3411e40626c75646bb19d2bb2f7bf2f63130918220a206758cbc48845fd725a695', + 'X-Appwrite-Project': '60479fe35d95d' + }} + + const resDb = http.get('http://localhost:9501/', config); + + check(resDb, { + 'status is 200': (r) => r.status === 200, + }); +} \ No newline at end of file diff --git a/tests/benchmarks/ws.js b/tests/benchmarks/ws.js new file mode 100644 index 0000000000..916458856f --- /dev/null +++ b/tests/benchmarks/ws.js @@ -0,0 +1,59 @@ +// k6 run tests/benchmarks/ws.js + +import { URL } from 'https://jslib.k6.io/url/1.0.0/index.js'; +import ws from 'k6/ws'; +import { check } from 'k6'; + +export let options = { + stages: [ + { + duration: '10s', + target: 500 + }, + { + duration: '1m', + target: 500 + }, + ], +} + +export default function () { + // const url = new URL('wss://appwrite-realtime.monitor-api.com/v1/realtime'); + // url.searchParams.append('project', '604249e6b1a9f'); + const url = new URL('ws://localhost/v1/realtime'); + url.searchParams.append('project', 'console'); + url.searchParams.append('channels[]', 'files'); + + const res = ws.connect(url.toString(), function (socket) { + let connection = false; + let checked = false; + let payload = null; + socket.on('open', () => { + connection = true; + }); + + socket.on('message', (data) => { + payload = data; + checked = true; + }); + + socket.setTimeout(function () { + check(payload, { + 'connection opened': (r) => connection, + 'message received': (r) => checked, + 'channels are right': (r) => r === JSON.stringify({ + "type": "connected", + "data": { + "channels": [ + "files" + ], + "user": null + } + }) + }) + socket.close(); + }, 5000); + }); + + check(res, { 'status is 101': (r) => r && r.status === 101 }); +} \ No newline at end of file diff --git a/tests/e2e/General/AbuseTest.php b/tests/e2e/General/AbuseTest.php index 0db8ce04d9..f5a2829974 100644 --- a/tests/e2e/General/AbuseTest.php +++ b/tests/e2e/General/AbuseTest.php @@ -8,16 +8,16 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideNone; use Utopia\App; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class AbuseTest extends Scope { use ProjectCustom; use SideNone; - public function setUp(): void + protected function setUp(): void { parent::setUp(); diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index 6fffb037ab..a8598d01c3 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -9,8 +9,9 @@ use Tests\E2E\Scopes\SideServer; use CURLFile; use Tests\E2E\Services\Functions\FunctionsBase; use Utopia\Database\DateTime; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\DatetimeValidator; class UsageTest extends Scope { @@ -45,8 +46,8 @@ class UsageTest extends Scope $headers['x-appwrite-key'] = $project['apiKey']; $headers['content-type'] = 'application/json'; - $usersCount = 0; - $requestsCount = 0; + $usersTotal = 0; + $requestsTotal = 0; for ($i = 0; $i < self::CREATE; $i++) { $email = uniqid() . 'user@usage.test'; $password = 'password'; @@ -65,23 +66,23 @@ class UsageTest extends Scope $this->assertEquals($email, $res['body']['email']); $this->assertNotEmpty($res['body']['$id']); - $usersCount++; - $requestsCount++; + $usersTotal++; + $requestsTotal++; if ($i < (self::CREATE / 2)) { $userId = $res['body']['$id']; $res = $this->client->call(Client::METHOD_DELETE, '/users/' . $userId, $headers); $this->assertEmpty($res['body']); - $requestsCount++; - $usersCount--; + $requestsTotal++; + $usersTotal--; } } return [ 'projectId' => $projectId, 'headers' => $headers, - 'usersCount' => $usersCount, - 'requestsCount' => $requestsCount + 'usersTotal' => $usersTotal, + 'requestsTotal' => $requestsTotal ]; } @@ -94,8 +95,8 @@ class UsageTest extends Scope $projectId = $data['projectId']; $headers = $data['headers']; - $usersCount = $data['usersCount']; - $requestsCount = $data['requestsCount']; + $usersTotal = $data['usersTotal']; + $requestsTotal = $data['requestsTotal']; $consoleHeaders = [ 'origin' => 'http://localhost', @@ -114,12 +115,12 @@ class UsageTest extends Scope $this->assertEquals('24h', $res['range']); $this->assertEquals(9, count($res)); - $this->assertEquals(24, count($res['requests'])); - $this->assertEquals(24, count($res['users'])); - $this->assertEquals($usersCount, $res['users'][array_key_last($res['users'])]['value']); - $this->validateDates($res['users']); - $this->assertEquals($requestsCount, $res['requests'][array_key_last($res['requests'])]['value']); - $this->validateDates($res['requests']); + $this->assertEquals(24, count($res['requestsTotal'])); + $this->assertEquals(24, count($res['usersTotal'])); + $this->assertEquals($usersTotal, $res['usersTotal'][array_key_last($res['usersTotal'])]['value']); + $this->validateDates($res['usersTotal']); + $this->assertEquals($requestsTotal, $res['requestsTotal'][array_key_last($res['requestsTotal'])]['value']); + $this->validateDates($res['requestsTotal']); $res = $this->client->call( Client::METHOD_GET, @@ -129,15 +130,15 @@ class UsageTest extends Scope $res = $res['body']; $this->assertEquals('90d', $res['range']); - $this->assertEquals(90, count($res['usersCount'])); - $this->assertEquals(90, count($res['sessionsCount'])); - $this->assertEquals((self::CREATE / 2), $res['usersCount'][array_key_last($res['usersCount'])]['value']); + $this->assertEquals(90, count($res['usersTotal'])); + $this->assertEquals(90, count($res['sessionsTotal'])); + $this->assertEquals((self::CREATE / 2), $res['usersTotal'][array_key_last($res['usersTotal'])]['value']); return [ 'projectId' => $projectId, 'headers' => $headers, 'consoleHeaders' => $consoleHeaders, - 'requestsCount' => $requestsCount, + 'requestsTotal' => $requestsTotal, ]; } @@ -145,10 +146,10 @@ class UsageTest extends Scope public function testPrepareStorageStats(array $data): array { $headers = $data['headers']; - $bucketsCount = 0; - $requestsCount = $data['requestsCount']; + $bucketsTotal = 0; + $requestsTotal = $data['requestsTotal']; $storageTotal = 0; - $filesCount = 0; + $filesTotal = 0; for ($i = 0; $i < self::CREATE; $i++) { @@ -177,8 +178,8 @@ class UsageTest extends Scope $this->assertEquals($name, $res['body']['name']); $this->assertNotEmpty($res['body']['$id']); $bucketId = $res['body']['$id']; - $bucketsCount++; - $requestsCount++; + $bucketsTotal++; + $requestsTotal++; if ($i < (self::CREATE / 2)) { $res = $this->client->call( @@ -187,8 +188,8 @@ class UsageTest extends Scope $headers ); $this->assertEmpty($res['body']); - $requestsCount++; - $bucketsCount--; + $requestsTotal++; + $bucketsTotal--; } } @@ -229,8 +230,8 @@ class UsageTest extends Scope $fileSize = $res['body']['sizeOriginal']; $storageTotal += $fileSize; - $filesCount++; - $requestsCount++; + $filesTotal++; + $requestsTotal++; $fileId = $res['body']['$id']; if ($i < (self::CREATE / 2)) { @@ -240,18 +241,18 @@ class UsageTest extends Scope $headers ); $this->assertEmpty($res['body']); - $requestsCount++; - $filesCount--; + $requestsTotal++; + $filesTotal--; $storageTotal -= $fileSize; } } return array_merge($data, [ 'bucketId' => $bucketId, - 'bucketsCount' => $bucketsCount, - 'requestsCount' => $requestsCount, + 'bucketsTotal' => $bucketsTotal, + 'requestsTotal' => $requestsTotal, 'storageTotal' => $storageTotal, - 'filesCount' => $filesCount, + 'filesTotal' => $filesTotal, ]); } @@ -261,10 +262,10 @@ class UsageTest extends Scope public function testStorageStats(array $data): array { $bucketId = $data['bucketId']; - $bucketsCount = $data['bucketsCount']; - $requestsCount = $data['requestsCount']; + $bucketsTotal = $data['bucketsTotal']; + $requestsTotal = $data['requestsTotal']; $storageTotal = $data['storageTotal']; - $filesCount = $data['filesCount']; + $filesTotal = $data['filesTotal']; sleep(self::WAIT); @@ -279,12 +280,12 @@ class UsageTest extends Scope $res = $res['body']; $this->assertEquals(9, count($res)); - $this->assertEquals(30, count($res['requests'])); - $this->assertEquals(30, count($res['storage'])); - $this->assertEquals($requestsCount, $res['requests'][array_key_last($res['requests'])]['value']); - $this->validateDates($res['requests']); - $this->assertEquals($storageTotal, $res['storage'][array_key_last($res['storage'])]['value']); - $this->validateDates($res['storage']); + $this->assertEquals(30, count($res['requestsTotal'])); + $this->assertEquals(30, count($res['filesStorage'])); + $this->assertEquals($requestsTotal, $res['requestsTotal'][array_key_last($res['requestsTotal'])]['value']); + $this->validateDates($res['requestsTotal']); + $this->assertEquals($storageTotal, $res['filesStorage'][array_key_last($res['filesStorage'])]['value']); + $this->validateDates($res['filesStorage']); $res = $this->client->call( Client::METHOD_GET, @@ -296,12 +297,12 @@ class UsageTest extends Scope ); $res = $res['body']; - $this->assertEquals($storageTotal, $res['filesStorage'][array_key_last($res['filesStorage'])]['value']); + $this->assertEquals($storageTotal, $res['filesStorage'][array_key_last($res['filesTotal'])]['value']); $this->validateDates($res['filesStorage']); - $this->assertEquals($bucketsCount, $res['bucketsCount'][array_key_last($res['bucketsCount'])]['value']); - $this->validateDates($res['bucketsCount']); - $this->assertEquals($filesCount, $res['filesCount'][array_key_last($res['filesCount'])]['value']); - $this->validateDates($res['filesCount']); + $this->assertEquals($bucketsTotal, $res['bucketsTotal'][array_key_last($res['bucketsTotal'])]['value']); + $this->validateDates($res['bucketsTotal']); + $this->assertEquals($filesTotal, $res['filesTotal'][array_key_last($res['filesTotal'])]['value']); + $this->validateDates($res['filesTotal']); $res = $this->client->call( Client::METHOD_GET, @@ -314,9 +315,9 @@ class UsageTest extends Scope $res = $res['body']; $this->assertEquals($storageTotal, $res['filesStorage'][array_key_last($res['filesStorage'])]['value']); - $this->assertEquals($filesCount, $res['filesCount'][array_key_last($res['filesCount'])]['value']); + $this->assertEquals($filesTotal, $res['filesTotal'][array_key_last($res['filesTotal'])]['value']); - $data['requestsCount'] = $requestsCount; + $data['requestsTotal'] = $requestsTotal; return $data; } @@ -326,10 +327,10 @@ class UsageTest extends Scope { $headers = $data['headers']; - $requestsCount = $data['requestsCount']; - $databasesCount = 0; - $collectionsCount = 0; - $documentsCount = 0; + $requestsTotal = $data['requestsTotal']; + $databasesTotal = 0; + $collectionsTotal = 0; + $documentsTotal = 0; for ($i = 0; $i < self::CREATE; $i++) { $name = uniqid() . ' database'; @@ -348,8 +349,8 @@ class UsageTest extends Scope $this->assertNotEmpty($res['body']['$id']); $databaseId = $res['body']['$id']; - $requestsCount++; - $databasesCount++; + $requestsTotal++; + $databasesTotal++; if ($i < (self::CREATE / 2)) { $res = $this->client->call( @@ -359,8 +360,8 @@ class UsageTest extends Scope ); $this->assertEmpty($res['body']); - $databasesCount--; - $requestsCount++; + $databasesTotal--; + $requestsTotal++; } } @@ -387,8 +388,8 @@ class UsageTest extends Scope $this->assertNotEmpty($res['body']['$id']); $collectionId = $res['body']['$id']; - $requestsCount++; - $collectionsCount++; + $requestsTotal++; + $collectionsTotal++; if ($i < (self::CREATE / 2)) { $res = $this->client->call( @@ -397,15 +398,15 @@ class UsageTest extends Scope $headers ); $this->assertEmpty($res['body']); - $collectionsCount--; - $requestsCount++; + $collectionsTotal--; + $requestsTotal++; } } $res = $this->client->call( Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes' . '/string', - array_merge($headers, ['content-type' => 'multipart/form-data']), + $headers, [ 'key' => 'name', 'size' => 255, @@ -414,7 +415,7 @@ class UsageTest extends Scope ); $this->assertEquals('name', $res['body']['key']); - $requestsCount++; + $requestsTotal++; sleep(self::WAIT); @@ -433,8 +434,8 @@ class UsageTest extends Scope $this->assertNotEmpty($res['body']['$id']); $documentId = $res['body']['$id']; - $requestsCount++; - $documentsCount++; + $requestsTotal++; + $documentsTotal++; if ($i < (self::CREATE / 2)) { $res = $this->client->call( @@ -443,18 +444,18 @@ class UsageTest extends Scope $headers ); $this->assertEmpty($res['body']); - $documentsCount--; - $requestsCount++; + $documentsTotal--; + $requestsTotal++; } } return array_merge($data, [ 'databaseId' => $databaseId, 'collectionId' => $collectionId, - 'requestsCount' => $requestsCount, - 'databasesCount' => $databasesCount, - 'collectionsCount' => $collectionsCount, - 'documentsCount' => $documentsCount, + 'requestsTotal' => $requestsTotal, + 'databasesTotal' => $databasesTotal, + 'collectionsTotal' => $collectionsTotal, + 'documentsTotal' => $documentsTotal, ]); } @@ -466,10 +467,10 @@ class UsageTest extends Scope $projectId = $data['projectId']; $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; - $requestsCount = $data['requestsCount']; - $databasesCount = $data['databasesCount']; - $collectionsCount = $data['collectionsCount']; - $documentsCount = $data['documentsCount']; + $requestsTotal = $data['requestsTotal']; + $databasesTotal = $data['databasesTotal']; + $collectionsTotal = $data['collectionsTotal']; + $documentsTotal = $data['documentsTotal']; sleep(self::WAIT); @@ -481,14 +482,14 @@ class UsageTest extends Scope $res = $res['body']; $this->assertEquals(9, count($res)); - $this->assertEquals(30, count($res['requests'])); - $this->assertEquals(30, count($res['storage'])); - $this->assertEquals($requestsCount, $res['requests'][array_key_last($res['requests'])]['value']); - $this->validateDates($res['requests']); - $this->assertEquals($databasesCount, $res['databases'][array_key_last($res['databases'])]['value']); - $this->validateDates($res['databases']); - $this->assertEquals($documentsCount, $res['documents'][array_key_last($res['documents'])]['value']); - $this->validateDates($res['documents']); + $this->assertEquals(30, count($res['requestsTotal'])); + $this->assertEquals(30, count($res['filesStorage'])); + $this->assertEquals($requestsTotal, $res['requestsTotal'][array_key_last($res['requestsTotal'])]['value']); + $this->validateDates($res['requestsTotal']); + $this->assertEquals($databasesTotal, $res['databasesTotal'][array_key_last($res['databasesTotal'])]['value']); + $this->validateDates($res['databasesTotal']); + $this->assertEquals($documentsTotal, $res['documentsTotal'][array_key_last($res['documentsTotal'])]['value']); + $this->validateDates($res['documentsTotal']); $res = $this->client->call( Client::METHOD_GET, @@ -497,12 +498,12 @@ class UsageTest extends Scope ); $res = $res['body']; - $this->assertEquals($databasesCount, $res['databasesCount'][array_key_last($res['databasesCount'])]['value']); - $this->validateDates($res['databasesCount']); - $this->assertEquals($collectionsCount, $res['collectionsCount'][array_key_last($res['collectionsCount'])]['value']); - $this->validateDates($res['collectionsCount']); - $this->assertEquals($documentsCount, $res['documentsCount'][array_key_last($res['documentsCount'])]['value']); - $this->validateDates($res['documentsCount']); + $this->assertEquals($databasesTotal, $res['databasesTotal'][array_key_last($res['databasesTotal'])]['value']); + $this->validateDates($res['databasesTotal']); + $this->assertEquals($collectionsTotal, $res['collectionsTotal'][array_key_last($res['collectionsTotal'])]['value']); + $this->validateDates($res['collectionsTotal']); + $this->assertEquals($documentsTotal, $res['documentsTotal'][array_key_last($res['documentsTotal'])]['value']); + $this->validateDates($res['documentsTotal']); $res = $this->client->call( Client::METHOD_GET, @@ -511,19 +512,19 @@ class UsageTest extends Scope ); $res = $res['body']; - $this->assertEquals($collectionsCount, $res['collectionsCount'][array_key_last($res['collectionsCount'])]['value']); - $this->validateDates($res['collectionsCount']); + $this->assertEquals($collectionsTotal, $res['collectionsTotal'][array_key_last($res['collectionsTotal'])]['value']); + $this->validateDates($res['collectionsTotal']); - $this->assertEquals($documentsCount, $res['documentsCount'][array_key_last($res['documentsCount'])]['value']); - $this->validateDates($res['documentsCount']); + $this->assertEquals($documentsTotal, $res['documentsTotal'][array_key_last($res['documentsTotal'])]['value']); + $this->validateDates($res['documentsTotal']); $res = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/usage?range=30d', $data['consoleHeaders']); $res = $res['body']; - $this->assertEquals($documentsCount, $res['documentsCount'][array_key_last($res['documentsCount'])]['value']); - $this->validateDates($res['documentsCount']); + $this->assertEquals($documentsTotal, $res['documentsTotal'][array_key_last($res['documentsTotal'])]['value']); + $this->validateDates($res['documentsTotal']); - $data['requestsCount'] = $requestsCount; + $data['requestsTotal'] = $requestsTotal; return $data; } @@ -582,7 +583,7 @@ class UsageTest extends Scope $this->assertEquals(202, $deployment['headers']['status-code']); $this->assertNotEmpty($deployment['body']['$id']); - $this->assertEquals(true, DateTime::isValid($deployment['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($deployment['body']['$createdAt'])); $this->assertEquals('index.php', $deployment['body']['entrypoint']); // Wait for deployment to build. @@ -596,8 +597,10 @@ class UsageTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['$createdAt'])); - $this->assertEquals(true, DateTime::isValid($response['body']['$updatedAt'])); + + + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$updatedAt'])); $this->assertEquals($deploymentId, $response['body']['deployment']); $execution = $this->client->call( @@ -695,20 +698,19 @@ class UsageTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(8, count($response['body'])); $this->assertEquals('30d', $response['body']['range']); - $this->assertIsArray($response['body']['deployments']); + $this->assertIsArray($response['body']['deploymentsTotal']); $this->assertIsArray($response['body']['deploymentsStorage']); - $this->assertIsArray($response['body']['builds']); - $this->assertIsArray($response['body']['buildsCompute']); - $this->assertIsArray($response['body']['executions']); - $this->assertIsArray($response['body']['executionsCompute']); + $this->assertIsArray($response['body']['buildsTotal']); + $this->assertIsArray($response['body']['buildsTime']); + $this->assertIsArray($response['body']['executionsTotal']); + $this->assertIsArray($response['body']['executionsTime']); $response = $response['body']; - $this->assertEquals($executions, $response['executions'][array_key_last($response['executions'])]['value']); - $this->validateDates($response['executions']); - - $this->assertEquals($executionTime, $response['executionsCompute'][array_key_last($response['executionsCompute'])]['value']); - $this->validateDates($response['executionsCompute']); + $this->assertEquals($executions, $response['executionsTotal'][array_key_last($response['executionsTotal'])]['value']); + $this->validateDates($response['executionsTotal']); + $this->assertEquals($executionTime, $response['executionsTime'][array_key_last($response['executionsTime'])]['value']); + $this->validateDates($response['executionsTime']); $response = $this->client->call( Client::METHOD_GET, @@ -719,28 +721,28 @@ class UsageTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(9, count($response['body'])); $this->assertEquals($response['body']['range'], '30d'); - $this->assertIsArray($response['body']['functions']); - $this->assertIsArray($response['body']['deployments']); + $this->assertIsArray($response['body']['functionsTotal']); + $this->assertIsArray($response['body']['deploymentsTotal']); $this->assertIsArray($response['body']['deploymentsStorage']); - $this->assertIsArray($response['body']['builds']); - $this->assertIsArray($response['body']['buildsCompute']); - $this->assertIsArray($response['body']['executions']); - $this->assertIsArray($response['body']['executionsCompute']); + $this->assertIsArray($response['body']['buildsTotal']); + $this->assertIsArray($response['body']['buildsTime']); + $this->assertIsArray($response['body']['executionsTotal']); + $this->assertIsArray($response['body']['executionsTime']); $response = $response['body']; - $this->assertEquals($executions, $response['executions'][array_key_last($response['executions'])]['value']); - $this->validateDates($response['executions']); - $this->assertEquals($executionTime, $response['executionsCompute'][array_key_last($response['executionsCompute'])]['value']); - $this->validateDates($response['executionsCompute']); - $this->assertGreaterThan(0, $response['buildsCompute'][array_key_last($response['buildsCompute'])]['value']); - $this->validateDates($response['buildsCompute']); + $this->assertEquals($executions, $response['executionsTotal'][array_key_last($response['executionsTotal'])]['value']); + $this->validateDates($response['executionsTotal']); + $this->assertEquals($executionTime, $response['executionsTime'][array_key_last($response['executionsTime'])]['value']); + $this->validateDates($response['executionsTime']); + $this->assertGreaterThan(0, $response['buildsTime'][array_key_last($response['buildsTime'])]['value']); + $this->validateDates($response['buildsTime']); } public function tearDown(): void { - $this->usersCount = 0; - $this->requestsCount = 0; + $this->usersTotal = 0; + $this->requestsTotal = 0; $projectId = ''; $headers = []; } diff --git a/tests/e2e/Scopes/ProjectConsole.php b/tests/e2e/Scopes/ProjectConsole.php index bc8ce4c0cf..dcc4aa7c33 100644 --- a/tests/e2e/Scopes/ProjectConsole.php +++ b/tests/e2e/Scopes/ProjectConsole.php @@ -2,7 +2,7 @@ namespace Tests\E2E\Scopes; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; trait ProjectConsole { diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index f2e4e84685..4d780d04c6 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -3,7 +3,7 @@ namespace Tests\E2E\Scopes; use Tests\E2E\Client; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; trait ProjectCustom { diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index 1858e41b8e..939de516b6 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -5,7 +5,7 @@ namespace Tests\E2E\Scopes; use Appwrite\Tests\Retryable; use Tests\E2E\Client; use PHPUnit\Framework\TestCase; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; abstract class Scope extends TestCase { @@ -21,7 +21,7 @@ abstract class Scope extends TestCase */ protected $endpoint = 'http://localhost/v1'; - public function setUp(): void + protected function setUp(): void { $this->client = new Client(); @@ -30,7 +30,7 @@ abstract class Scope extends TestCase ; } - public function tearDown(): void + protected function tearDown(): void { $this->client = null; } diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index e8bf146316..967105ecd6 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -4,8 +4,9 @@ namespace Tests\E2E\Services\Account; use Appwrite\Tests\Retry; use Tests\E2E\Client; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; use Utopia\Database\DateTime; +use Utopia\Database\Validator\DatetimeValidator; trait AccountBase { @@ -34,7 +35,7 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 201); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $name); @@ -198,7 +199,7 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $name); @@ -343,7 +344,7 @@ trait AccountBase $this->assertIsNumeric($response['body']['total']); $this->assertContains($response['body']['logs'][1]['event'], ["session.create"]); $this->assertEquals($response['body']['logs'][1]['ip'], filter_var($response['body']['logs'][1]['ip'], FILTER_VALIDATE_IP)); - $this->assertEquals(true, DateTime::isValid($response['body']['logs'][1]['time'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][1]['time'])); $this->assertEquals('Windows', $response['body']['logs'][1]['osName']); $this->assertEquals('WIN', $response['body']['logs'][1]['osCode']); @@ -365,7 +366,7 @@ trait AccountBase $this->assertContains($response['body']['logs'][2]['event'], ["user.create"]); $this->assertEquals($response['body']['logs'][2]['ip'], filter_var($response['body']['logs'][2]['ip'], FILTER_VALIDATE_IP)); - $this->assertEquals(true, DateTime::isValid($response['body']['logs'][2]['time'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['logs'][2]['time'])); $this->assertEquals('Windows', $response['body']['logs'][2]['osName']); $this->assertEquals('WIN', $response['body']['logs'][2]['osCode']); @@ -476,7 +477,7 @@ trait AccountBase $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $newName); @@ -543,7 +544,7 @@ trait AccountBase $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ @@ -633,7 +634,7 @@ trait AccountBase $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $newEmail); /** @@ -675,7 +676,7 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 201); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $data['email']); $this->assertEquals($response['body']['name'], $data['name']); @@ -817,7 +818,7 @@ trait AccountBase $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals(true, DateTime::isValid($response['body']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); $lastEmail = $this->getLastEmail(); @@ -1119,7 +1120,7 @@ trait AccountBase $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals(true, DateTime::isValid($response['body']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); $lastEmail = $this->getLastEmail(); @@ -1273,7 +1274,7 @@ trait AccountBase $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals(true, DateTime::isValid($response['body']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); $userId = $response['body']['userId']; @@ -1379,7 +1380,7 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertTrue($response['body']['emailVerification']); @@ -1439,7 +1440,7 @@ trait AccountBase $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ diff --git a/tests/e2e/Services/Account/AccountConsoleClientTest.php b/tests/e2e/Services/Account/AccountConsoleClientTest.php index 69bb503428..c8ebedd991 100644 --- a/tests/e2e/Services/Account/AccountConsoleClientTest.php +++ b/tests/e2e/Services/Account/AccountConsoleClientTest.php @@ -6,9 +6,10 @@ use Appwrite\Extend\Exception; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; use Utopia\Database\DateTime; use Tests\E2E\Client; +use Utopia\Database\Validator\DatetimeValidator; class AccountConsoleClientTest extends Scope { @@ -72,7 +73,7 @@ class AccountConsoleClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $name); @@ -92,7 +93,7 @@ class AccountConsoleClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $name); } diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index ea24d06bdb..9018ed0679 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -9,7 +9,8 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; use Utopia\Database\DateTime; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\DatetimeValidator; use function sleep; @@ -475,7 +476,7 @@ class AccountCustomClientTest extends Scope $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ @@ -726,7 +727,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals(true, DateTime::isValid($response['body']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); $userId = $response['body']['userId']; @@ -826,7 +827,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['phone'], $number); $this->assertTrue($response['body']['phoneVerification']); @@ -877,7 +878,7 @@ class AccountCustomClientTest extends Scope $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ @@ -919,7 +920,7 @@ class AccountCustomClientTest extends Scope $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['phone'], $newPhone); /** @@ -968,7 +969,7 @@ class AccountCustomClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); $this->assertEmpty($response['body']['secret']); - $this->assertEquals(true, DateTime::isValid($response['body']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['expire'])); \sleep(2); diff --git a/tests/e2e/Services/Account/AccountCustomServerTest.php b/tests/e2e/Services/Account/AccountCustomServerTest.php index 85d140c829..143277608d 100644 --- a/tests/e2e/Services/Account/AccountCustomServerTest.php +++ b/tests/e2e/Services/Account/AccountCustomServerTest.php @@ -6,7 +6,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; class AccountCustomServerTest extends Scope { diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index a183325039..5bd427979e 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -3,11 +3,11 @@ namespace Tests\E2E\Services\Databases; use Tests\E2E\Client; -use Utopia\Database\Database; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; use Utopia\Database\DateTime; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\DatetimeValidator; trait DatabasesBase { @@ -1532,8 +1532,8 @@ trait DatabasesBase $this->assertEquals($databaseId, $document['body']['$databaseId']); $this->assertEquals($document['body']['title'], 'Thor: Ragnaroc'); $this->assertEquals($document['body']['releaseYear'], 2017); - $this->assertEquals(true, DateTime::isValid($document['body']['$createdAt'])); - $this->assertEquals(true, DateTime::isValid($document['body']['birthDay'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($document['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($document['body']['birthDay'])); $this->assertContains(Permission::read(Role::user($this->getUser()['$id'])), $document['body']['$permissions']); $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $document['body']['$permissions']); $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $document['body']['$permissions']); diff --git a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php index cdbeda00b6..4e2d28bcf8 100644 --- a/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesConsoleClientTest.php @@ -6,9 +6,9 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Client; use Tests\E2E\Scopes\SideConsole; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class DatabasesConsoleClientTest extends Scope { @@ -86,8 +86,8 @@ class DatabasesConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(count($response['body']), 3); $this->assertEquals($response['body']['range'], '24h'); - $this->assertIsArray($response['body']['documentsCount']); - $this->assertIsArray($response['body']['collectionsCount']); + $this->assertIsArray($response['body']['documentsTotal']); + $this->assertIsArray($response['body']['collectionsTotal']); } @@ -131,7 +131,7 @@ class DatabasesConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(count($response['body']), 2); $this->assertEquals($response['body']['range'], '24h'); - $this->assertIsArray($response['body']['documentsCount']); + $this->assertIsArray($response['body']['documentsTotal']); } /** diff --git a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php index 9f86bb66c0..748070161d 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomClientTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomClientTest.php @@ -6,9 +6,9 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class DatabasesCustomClientTest extends Scope { diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index bd4e8aa77b..19a56941eb 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -6,10 +6,9 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; use Tests\E2E\Client; -use Utopia\Database\Database; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class DatabasesCustomServerTest extends Scope { diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php index 1c15a363a8..b1d197f010 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsGuestTest.php @@ -6,9 +6,9 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; class DatabasesPermissionsGuestTest extends Scope diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php index 59091956b0..860fb7fb12 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsMemberTest.php @@ -6,9 +6,9 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class DatabasesPermissionsMemberTest extends Scope { diff --git a/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php b/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php index 07275c7524..8377b9c803 100644 --- a/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php +++ b/tests/e2e/Services/Databases/DatabasesPermissionsTeamTest.php @@ -6,9 +6,9 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class DatabasesPermissionsTeamTest extends Scope { diff --git a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php index 9cba3719cb..b473b082ca 100644 --- a/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsConsoleClientTest.php @@ -6,8 +6,8 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Client; use Tests\E2E\Scopes\SideConsole; -use Utopia\Database\ID; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Role; class FunctionsConsoleClientTest extends Scope { diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 56b72e4468..cd669a6b5e 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -7,10 +7,8 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideClient; -use Utopia\CLI\Console; -use Utopia\Database\Database; -use Utopia\Database\ID; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Role; class FunctionsCustomClientTest extends Scope { diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index e97c1412b6..0229ccbf58 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -8,10 +8,9 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; -use Utopia\CLI\Console; -use Utopia\Database\Database; use Utopia\Database\DateTime; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\DatetimeValidator; class FunctionsCustomServerTest extends Scope { @@ -45,8 +44,8 @@ class FunctionsCustomServerTest extends Scope $this->assertNotEmpty($response1['body']['$id']); $this->assertEquals('Test', $response1['body']['name']); $this->assertEquals('php-8.0', $response1['body']['runtime']); - $this->assertEquals(true, DateTime::isValid($response1['body']['$createdAt'])); - $this->assertEquals(true, DateTime::isValid($response1['body']['$updatedAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response1['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response1['body']['$updatedAt'])); $this->assertEquals('', $response1['body']['deployment']); $this->assertEquals([ 'users.*.create', @@ -328,8 +327,8 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $response1['headers']['status-code']); $this->assertNotEmpty($response1['body']['$id']); $this->assertEquals('Test1', $response1['body']['name']); - $this->assertEquals(true, DateTime::isValid($response1['body']['$createdAt'])); - $this->assertEquals(true, DateTime::isValid($response1['body']['$updatedAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response1['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response1['body']['$updatedAt'])); $this->assertEquals('', $response1['body']['deployment']); $this->assertEquals([ 'users.*.update.name', @@ -369,7 +368,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(202, $deployment['headers']['status-code']); $this->assertNotEmpty($deployment['body']['$id']); - $this->assertEquals(true, DateTime::isValid($deployment['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($deployment['body']['$createdAt'])); $this->assertEquals('index.php', $deployment['body']['entrypoint']); // Wait for deployment to build. @@ -418,7 +417,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(202, $largeTag['headers']['status-code']); $this->assertNotEmpty($largeTag['body']['$id']); - $this->assertEquals(true, DateTime::isValid($largeTag['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($largeTag['body']['$createdAt'])); $this->assertEquals('index.php', $largeTag['body']['entrypoint']); $this->assertGreaterThan(10000, $largeTag['body']['size']); @@ -440,8 +439,8 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['$createdAt'])); - $this->assertEquals(true, DateTime::isValid($response['body']['$updatedAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$updatedAt'])); $this->assertEquals($data['deploymentId'], $response['body']['deployment']); /** @@ -606,7 +605,7 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(202, $execution['headers']['status-code']); $this->assertNotEmpty($execution['body']['$id']); $this->assertNotEmpty($execution['body']['functionId']); - $this->assertEquals(true, DateTime::isValid($execution['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($execution['body']['$createdAt'])); $this->assertEquals($data['functionId'], $execution['body']['functionId']); $this->assertEquals('waiting', $execution['body']['status']); $this->assertEquals(0, $execution['body']['statusCode']); @@ -623,7 +622,7 @@ class FunctionsCustomServerTest extends Scope $this->assertNotEmpty($execution['body']['$id']); $this->assertNotEmpty($execution['body']['functionId']); - $this->assertEquals(true, DateTime::isValid($execution['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($execution['body']['$createdAt'])); $this->assertEquals($data['functionId'], $execution['body']['functionId']); $this->assertEquals('completed', $execution['body']['status']); $this->assertEquals(200, $execution['body']['statusCode']); diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 789020bf42..1dfb331eeb 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -6,11 +6,9 @@ use Appwrite\Auth\Auth; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; -use Tests\E2E\Services\Projects\ProjectsBase; use Tests\E2E\Client; -use Utopia\Database\Database; use Utopia\Database\DateTime; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; class ProjectsConsoleClientTest extends Scope { @@ -355,14 +353,14 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(count($response['body']), 9); $this->assertNotEmpty($response['body']); $this->assertEquals('30d', $response['body']['range']); - $this->assertIsArray($response['body']['requests']); + $this->assertIsArray($response['body']['requestsTotal']); $this->assertIsArray($response['body']['network']); - $this->assertIsArray($response['body']['executions']); - $this->assertIsArray($response['body']['documents']); - $this->assertIsArray($response['body']['databases']); - $this->assertIsArray($response['body']['buckets']); - $this->assertIsArray($response['body']['users']); - $this->assertIsArray($response['body']['storage']); + $this->assertIsArray($response['body']['executionsTotal']); + $this->assertIsArray($response['body']['documentsTotal']); + $this->assertIsArray($response['body']['databasesTotal']); + $this->assertIsArray($response['body']['bucketsTotal']); + $this->assertIsArray($response['body']['usersTotal']); + $this->assertIsArray($response['body']['filesStorage']); /** * Test for FAILURE diff --git a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php index 500b3d48be..cd2fb6f13b 100644 --- a/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeConsoleClientTest.php @@ -8,9 +8,9 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideConsole; use Tests\E2E\Services\Functions\FunctionsBase; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class RealtimeConsoleClientTest extends Scope { diff --git a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php index f4b959274a..d4c8f53426 100644 --- a/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php +++ b/tests/e2e/Services/Realtime/RealtimeCustomClientTest.php @@ -8,9 +8,9 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; use Utopia\CLI\Console; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; use WebSocket\ConnectionException; class RealtimeCustomClientTest extends Scope diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index b4c28b0fa2..7063ad5a74 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -5,9 +5,10 @@ namespace Tests\E2E\Services\Storage; use CURLFile; use Tests\E2E\Client; use Utopia\Database\DateTime; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\DatetimeValidator; trait StorageBase { @@ -52,7 +53,7 @@ trait StorageBase ]); $this->assertEquals(201, $file['headers']['status-code']); $this->assertNotEmpty($file['body']['$id']); - $this->assertEquals(true, DateTime::isValid($file['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file['body']['$createdAt'])); $this->assertEquals('logo.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); @@ -120,7 +121,7 @@ trait StorageBase $this->assertEquals(201, $largeFile['headers']['status-code']); $this->assertNotEmpty($largeFile['body']['$id']); - $this->assertEquals(true, DateTime::isValid($largeFile['body']['$createdAt'])); + $this->assertEquals(true, $largeFile['body']['$createdAt']); $this->assertEquals('large-file.mp4', $largeFile['body']['name']); $this->assertEquals('video/mp4', $largeFile['body']['mimeType']); $this->assertEquals($totalSize, $largeFile['body']['sizeOriginal']); @@ -283,7 +284,7 @@ trait StorageBase ]); $this->assertEquals(201, $file['headers']['status-code']); $this->assertNotEmpty($file['body']['$id']); - $this->assertEquals(true, DateTime::isValid($file['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file['body']['$createdAt'])); $this->assertEquals('logo.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); @@ -373,7 +374,7 @@ trait StorageBase $this->assertEquals(200, $file1['headers']['status-code']); $this->assertNotEmpty($file1['body']['$id']); - $this->assertEquals(true, DateTime::isValid($file1['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file1['body']['$createdAt'])); $this->assertEquals('logo.png', $file1['body']['name']); $this->assertEquals('image/png', $file1['body']['mimeType']); $this->assertEquals(47218, $file1['body']['sizeOriginal']); @@ -712,7 +713,7 @@ trait StorageBase $this->assertEquals(200, $file['headers']['status-code']); $this->assertNotEmpty($file['body']['$id']); - $this->assertEquals(true, DateTime::isValid($file['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file['body']['$createdAt'])); $this->assertEquals('logo.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); diff --git a/tests/e2e/Services/Storage/StorageConsoleClientTest.php b/tests/e2e/Services/Storage/StorageConsoleClientTest.php index e24ac524a6..aff055f18d 100644 --- a/tests/e2e/Services/Storage/StorageConsoleClientTest.php +++ b/tests/e2e/Services/Storage/StorageConsoleClientTest.php @@ -6,7 +6,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideConsole; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; class StorageConsoleClientTest extends Scope { @@ -41,8 +41,8 @@ class StorageConsoleClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); $this->assertEquals(4, count($response['body'])); $this->assertEquals($response['body']['range'], '24h'); - $this->assertIsArray($response['body']['bucketsCount']); - $this->assertIsArray($response['body']['filesCount']); + $this->assertIsArray($response['body']['bucketsTotal']); + $this->assertIsArray($response['body']['filesTotal']); $this->assertIsArray($response['body']['filesStorage']); } @@ -97,7 +97,7 @@ class StorageConsoleClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); $this->assertEquals(count($response['body']), 3); $this->assertEquals($response['body']['range'], '24h'); - $this->assertIsArray($response['body']['filesCount']); + $this->assertIsArray($response['body']['filesTotal']); $this->assertIsArray($response['body']['filesStorage']); } } diff --git a/tests/e2e/Services/Storage/StorageCustomClientTest.php b/tests/e2e/Services/Storage/StorageCustomClientTest.php index fdb158ae5b..a11f736b23 100644 --- a/tests/e2e/Services/Storage/StorageCustomClientTest.php +++ b/tests/e2e/Services/Storage/StorageCustomClientTest.php @@ -13,10 +13,10 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; use Utopia\Database\DateTime; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; -use Utopia\Database\Validator\Authorization; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\DatetimeValidator; class StorageCustomClientTest extends Scope { @@ -63,7 +63,7 @@ class StorageCustomClientTest extends Scope $fileId = $file['body']['$id']; $this->assertEquals($file['headers']['status-code'], 201); $this->assertNotEmpty($fileId); - $this->assertEquals(true, DateTime::isValid($file['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file['body']['$createdAt'])); $this->assertEquals('permissions.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); @@ -159,7 +159,7 @@ class StorageCustomClientTest extends Scope $fileId = $file['body']['$id']; $this->assertEquals($file['headers']['status-code'], 201); $this->assertNotEmpty($fileId); - $this->assertEquals(true, DateTime::isValid($file['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file['body']['$createdAt'])); $this->assertEquals('permissions.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); @@ -245,7 +245,7 @@ class StorageCustomClientTest extends Scope $fileId = $file['body']['$id']; $this->assertEquals($file['headers']['status-code'], 201); $this->assertNotEmpty($fileId); - $this->assertEquals(true, DateTime::isValid($file['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file['body']['$createdAt'])); $this->assertEquals('permissions.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); @@ -370,7 +370,7 @@ class StorageCustomClientTest extends Scope $fileId = $file['body']['$id']; $this->assertEquals($file['headers']['status-code'], 201); $this->assertNotEmpty($fileId); - $this->assertEquals(true, DateTime::isValid($file['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file['body']['$createdAt'])); $this->assertEquals('permissions.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); @@ -548,7 +548,7 @@ class StorageCustomClientTest extends Scope $fileId = $file['body']['$id']; $this->assertEquals($file['headers']['status-code'], 201); $this->assertNotEmpty($fileId); - $this->assertEquals(true, DateTime::isValid($file['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file['body']['$createdAt'])); $this->assertEquals('permissions.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); @@ -710,7 +710,7 @@ class StorageCustomClientTest extends Scope $fileId = $file1['body']['$id']; $this->assertEquals($file1['headers']['status-code'], 201); $this->assertNotEmpty($fileId); - $this->assertEquals(true, DateTime::isValid($file1['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file1['body']['$createdAt'])); $this->assertEquals('permissions.png', $file1['body']['name']); $this->assertEquals('image/png', $file1['body']['mimeType']); $this->assertEquals(47218, $file1['body']['sizeOriginal']); @@ -799,7 +799,7 @@ class StorageCustomClientTest extends Scope $fileId = $file1['body']['$id']; $this->assertEquals($file1['headers']['status-code'], 201); $this->assertNotEmpty($fileId); - $this->assertEquals(true, DateTime::isValid($file1['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file1['body']['$createdAt'])); $this->assertEquals('permissions.png', $file1['body']['name']); $this->assertEquals('image/png', $file1['body']['mimeType']); $this->assertEquals(47218, $file1['body']['sizeOriginal']); @@ -888,7 +888,7 @@ class StorageCustomClientTest extends Scope $fileId = $file1['body']['$id']; $this->assertEquals($file1['headers']['status-code'], 201); $this->assertNotEmpty($fileId); - $this->assertEquals(true, DateTime::isValid($file1['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file1['body']['$createdAt'])); $this->assertEquals('permissions.png', $file1['body']['name']); $this->assertEquals('image/png', $file1['body']['mimeType']); $this->assertEquals(47218, $file1['body']['sizeOriginal']); @@ -1027,7 +1027,7 @@ class StorageCustomClientTest extends Scope $fileId = $file['body']['$id']; $this->assertEquals($file['headers']['status-code'], 201); $this->assertNotEmpty($fileId); - $this->assertEquals(true, DateTime::isValid($file['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file['body']['$createdAt'])); $this->assertEquals('permissions.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); @@ -1262,7 +1262,7 @@ class StorageCustomClientTest extends Scope $this->assertContains(Permission::read(Role::user($this->getUser()['$id'])), $file['body']['$permissions']); $this->assertContains(Permission::update(Role::user($this->getUser()['$id'])), $file['body']['$permissions']); $this->assertContains(Permission::delete(Role::user($this->getUser()['$id'])), $file['body']['$permissions']); - $this->assertEquals(true, DateTime::isValid($file['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($file['body']['$createdAt'])); $this->assertEquals('permissions.png', $file['body']['name']); $this->assertEquals('image/png', $file['body']['mimeType']); $this->assertEquals(47218, $file['body']['sizeOriginal']); diff --git a/tests/e2e/Services/Storage/StorageCustomServerTest.php b/tests/e2e/Services/Storage/StorageCustomServerTest.php index ac03f2b83c..a541e30d42 100644 --- a/tests/e2e/Services/Storage/StorageCustomServerTest.php +++ b/tests/e2e/Services/Storage/StorageCustomServerTest.php @@ -7,7 +7,8 @@ use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; use Utopia\Database\DateTime; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\DatetimeValidator; class StorageCustomServerTest extends Scope { @@ -30,7 +31,7 @@ class StorageCustomServerTest extends Scope ]); $this->assertEquals(201, $bucket['headers']['status-code']); $this->assertNotEmpty($bucket['body']['$id']); - $this->assertEquals(true, DateTime::isValid($bucket['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($bucket['body']['$createdAt'])); $this->assertIsArray($bucket['body']['$permissions']); $this->assertIsArray($bucket['body']['allowedFileExtensions']); $this->assertEquals('Test Bucket', $bucket['body']['name']); @@ -228,7 +229,7 @@ class StorageCustomServerTest extends Scope ]); $this->assertEquals(200, $bucket['headers']['status-code']); $this->assertNotEmpty($bucket['body']['$id']); - $this->assertEquals(true, DateTime::isValid($bucket['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($bucket['body']['$createdAt'])); $this->assertIsArray($bucket['body']['$permissions']); $this->assertIsArray($bucket['body']['allowedFileExtensions']); $this->assertEquals('Test Bucket Updated', $bucket['body']['name']); diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 854a041503..e6d03c6e4a 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -3,9 +3,9 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Client; -use Utopia\Database\Database; use Utopia\Database\DateTime; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\DatetimeValidator; trait TeamsBase { @@ -28,7 +28,7 @@ trait TeamsBase $this->assertEquals('Arsenal', $response1['body']['name']); $this->assertGreaterThan(-1, $response1['body']['total']); $this->assertIsInt($response1['body']['total']); - $this->assertEquals(true, DateTime::isValid($response1['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response1['body']['$createdAt'])); $teamUid = $response1['body']['$id']; $teamName = $response1['body']['name']; @@ -48,7 +48,7 @@ trait TeamsBase $this->assertEquals('Manchester United', $response2['body']['name']); $this->assertGreaterThan(-1, $response2['body']['total']); $this->assertIsInt($response2['body']['total']); - $this->assertEquals(true, DateTime::isValid($response2['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response2['body']['$createdAt'])); $response3 = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ 'content-type' => 'application/json', @@ -63,7 +63,7 @@ trait TeamsBase $this->assertEquals('Newcastle', $response3['body']['name']); $this->assertGreaterThan(-1, $response3['body']['total']); $this->assertIsInt($response3['body']['total']); - $this->assertEquals(true, DateTime::isValid($response3['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response3['body']['$createdAt'])); /** * Test for FAILURE */ @@ -98,7 +98,7 @@ trait TeamsBase $this->assertEquals('Arsenal', $response['body']['name']); $this->assertGreaterThan(-1, $response['body']['total']); $this->assertIsInt($response['body']['total']); - $this->assertEquals(true, DateTime::isValid($response['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); /** * Test for FAILURE @@ -275,7 +275,7 @@ trait TeamsBase $this->assertEquals('Demo', $response['body']['name']); $this->assertGreaterThan(-1, $response['body']['total']); $this->assertIsInt($response['body']['total']); - $this->assertEquals(true, DateTime::isValid($response['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); $response = $this->client->call(Client::METHOD_PUT, '/teams/' . $response['body']['$id'], array_merge([ 'content-type' => 'application/json', @@ -290,7 +290,7 @@ trait TeamsBase $this->assertEquals('Demo New', $response['body']['name']); $this->assertGreaterThan(-1, $response['body']['total']); $this->assertIsInt($response['body']['total']); - $this->assertEquals(true, DateTime::isValid($response['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); /** * Test for FAILURE @@ -326,7 +326,7 @@ trait TeamsBase $this->assertEquals('Demo', $response['body']['name']); $this->assertGreaterThan(-1, $response['body']['total']); $this->assertIsInt($response['body']['total']); - $this->assertEquals(true, DateTime::isValid($response['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid, array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 788626b102..e74a47c3f1 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -4,7 +4,8 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Client; use Utopia\Database\DateTime; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\DatetimeValidator; trait TeamsBaseClient { @@ -150,7 +151,7 @@ trait TeamsBaseClient $this->assertNotEmpty($response['body']['teamId']); $this->assertNotEmpty($response['body']['teamName']); $this->assertCount(2, $response['body']['roles']); - $this->assertEquals(false, DateTime::isValid($response['body']['joined'])); // is null in DB + $this->assertEquals(false, (new DatetimeValidator())->isValid($response['body']['joined'])); // is null in DB $this->assertEquals(false, $response['body']['confirm']); /** @@ -203,7 +204,7 @@ trait TeamsBaseClient $this->assertNotEmpty($response['body']['teamId']); $this->assertNotEmpty($response['body']['teamName']); $this->assertCount(2, $response['body']['roles']); - $this->assertEquals(false, DateTime::isValid($response['body']['joined'])); // is null in DB + $this->assertEquals(false, (new DatetimeValidator())->isValid($response['body']['joined'])); // is null in DB $this->assertEquals(false, $response['body']['confirm']); $lastEmail = $this->getLastEmail(); @@ -337,7 +338,7 @@ trait TeamsBaseClient $this->assertNotEmpty($response['body']['userId']); $this->assertNotEmpty($response['body']['teamId']); $this->assertCount(2, $response['body']['roles']); - $this->assertEquals(true, DateTime::isValid($response['body']['joined'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['joined'])); $this->assertEquals(true, $response['body']['confirm']); $session = $this->client->parseCookie((string)$response['headers']['set-cookie'])['a_session_' . $this->getProject()['$id']]; $data['session'] = $session; @@ -369,7 +370,7 @@ trait TeamsBaseClient $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $name); @@ -403,7 +404,7 @@ trait TeamsBaseClient $this->assertIsArray($response['body']); $this->assertNotEmpty($response['body']); $this->assertNotEmpty($response['body']['$id']); - $this->assertEquals(true, DateTime::isValid($response['body']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['registration'])); $this->assertEquals($response['body']['email'], $email); $this->assertEquals($response['body']['name'], $name); diff --git a/tests/e2e/Services/Teams/TeamsBaseServer.php b/tests/e2e/Services/Teams/TeamsBaseServer.php index c4d92ff0d9..4c2f1ede62 100644 --- a/tests/e2e/Services/Teams/TeamsBaseServer.php +++ b/tests/e2e/Services/Teams/TeamsBaseServer.php @@ -5,6 +5,7 @@ namespace Tests\E2E\Services\Teams; use Tests\E2E\Client; use Utopia\Database\Database; use Utopia\Database\DateTime; +use Utopia\Database\Validator\DatetimeValidator; trait TeamsBaseServer { @@ -57,7 +58,7 @@ trait TeamsBaseServer $this->assertNotEmpty($response['body']['teamId']); $this->assertNotEmpty($response['body']['teamName']); $this->assertCount(2, $response['body']['roles']); - $this->assertEquals(true, DateTime::isValid($response['body']['joined'])); // is null in DB + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['joined'])); // is null in DB $this->assertEquals(true, $response['body']['confirm']); /** @@ -108,7 +109,7 @@ trait TeamsBaseServer $this->assertEquals($email, $response['body']['userEmail']); $this->assertNotEmpty($response['body']['teamId']); $this->assertCount(2, $response['body']['roles']); - $this->assertEquals(true, DateTime::isValid($response['body']['joined'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['joined'])); $this->assertEquals(true, $response['body']['confirm']); $userUid = $response['body']['userId']; @@ -251,7 +252,7 @@ trait TeamsBaseServer $this->assertEquals('Arsenal', $response['body']['name']); $this->assertEquals(1, $response['body']['total']); $this->assertIsInt($response['body']['total']); - $this->assertEquals(true, DateTime::isValid($response['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); /** Delete User */ $user = $this->client->call(Client::METHOD_DELETE, '/users/' . $userUid, array_merge([ @@ -276,6 +277,6 @@ trait TeamsBaseServer $this->assertEquals('Arsenal', $response['body']['name']); $this->assertEquals(0, $response['body']['total']); $this->assertIsInt($response['body']['total']); - $this->assertEquals(true, DateTime::isValid($response['body']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($response['body']['$createdAt'])); } } diff --git a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php index 0f32425c92..e86c18a8e2 100644 --- a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php +++ b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php @@ -6,7 +6,7 @@ use Tests\E2E\Client; use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\SideClient; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; class TeamsConsoleClientTest extends Scope { diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index ac3b116b32..75cce56537 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -4,7 +4,7 @@ namespace Tests\E2E\Services\Users; use Appwrite\Tests\Retry; use Tests\E2E\Client; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; trait UsersBase { diff --git a/tests/e2e/Services/Users/UsersConsoleClientTest.php b/tests/e2e/Services/Users/UsersConsoleClientTest.php index 616a2ca38b..8943bfab63 100644 --- a/tests/e2e/Services/Users/UsersConsoleClientTest.php +++ b/tests/e2e/Services/Users/UsersConsoleClientTest.php @@ -40,7 +40,7 @@ class UsersConsoleClientTest extends Scope $this->assertEquals($response['headers']['status-code'], 200); $this->assertEquals(count($response['body']), 3); $this->assertEquals($response['body']['range'], '24h'); - $this->assertIsArray($response['body']['usersCount']); - $this->assertIsArray($response['body']['sessionsCount']); + $this->assertIsArray($response['body']['usersTotal']); + $this->assertIsArray($response['body']['sessionsTotal']); } } diff --git a/tests/e2e/Services/Webhooks/WebhooksBase.php b/tests/e2e/Services/Webhooks/WebhooksBase.php index bb7edfdb46..f07dd263fa 100644 --- a/tests/e2e/Services/Webhooks/WebhooksBase.php +++ b/tests/e2e/Services/Webhooks/WebhooksBase.php @@ -6,9 +6,10 @@ use Appwrite\Tests\Retry; use CURLFile; use Tests\E2E\Client; use Utopia\Database\DateTime; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\DatetimeValidator; trait WebhooksBase { @@ -529,7 +530,7 @@ trait WebhooksBase $this->assertNotEmpty($webhook['data']['$id']); $this->assertIsArray($webhook['data']['$permissions']); $this->assertEquals($webhook['data']['name'], 'logo.png'); - $this->assertEquals(true, DateTime::isValid($webhook['data']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['$createdAt'])); $this->assertNotEmpty($webhook['data']['signature']); $this->assertEquals($webhook['data']['mimeType'], 'image/png'); $this->assertEquals($webhook['data']['sizeOriginal'], 47218); @@ -587,7 +588,7 @@ trait WebhooksBase $this->assertNotEmpty($webhook['data']['$id']); $this->assertIsArray($webhook['data']['$permissions']); $this->assertEquals($webhook['data']['name'], 'logo.png'); - $this->assertEquals(true, DateTime::isValid($webhook['data']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['$createdAt'])); $this->assertNotEmpty($webhook['data']['signature']); $this->assertEquals($webhook['data']['mimeType'], 'image/png'); $this->assertEquals($webhook['data']['sizeOriginal'], 47218); @@ -637,7 +638,7 @@ trait WebhooksBase $this->assertNotEmpty($webhook['data']['$id']); $this->assertIsArray($webhook['data']['$permissions']); $this->assertEquals($webhook['data']['name'], 'logo.png'); - $this->assertEquals(true, DateTime::isValid($webhook['data']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['$createdAt'])); $this->assertNotEmpty($webhook['data']['signature']); $this->assertEquals($webhook['data']['mimeType'], 'image/png'); $this->assertEquals($webhook['data']['sizeOriginal'], 47218); @@ -719,7 +720,7 @@ trait WebhooksBase $this->assertEquals('Arsenal', $webhook['data']['name']); $this->assertGreaterThan(-1, $webhook['data']['total']); $this->assertIsInt($webhook['data']['total']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['$createdAt'])); /** * Test for FAILURE @@ -764,7 +765,7 @@ trait WebhooksBase $this->assertEquals('Demo New', $webhook['data']['name']); $this->assertGreaterThan(-1, $webhook['data']['total']); $this->assertIsInt($webhook['data']['total']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['$createdAt'])); /** * Test for FAILURE @@ -813,7 +814,7 @@ trait WebhooksBase $this->assertEquals('Chelsea', $webhook['data']['name']); $this->assertGreaterThan(-1, $webhook['data']['total']); $this->assertIsInt($webhook['data']['total']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['$createdAt'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['$createdAt'])); /** * Test for FAILURE @@ -874,7 +875,7 @@ trait WebhooksBase $this->assertNotEmpty($webhook['data']['userId']); $this->assertNotEmpty($webhook['data']['teamId']); $this->assertCount(2, $webhook['data']['roles']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['invited'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['invited'])); $this->assertEquals(('server' === $this->getSide()), $webhook['data']['confirm']); /** @@ -946,7 +947,7 @@ trait WebhooksBase $this->assertNotEmpty($webhook['data']['userId']); $this->assertNotEmpty($webhook['data']['teamId']); $this->assertCount(2, $webhook['data']['roles']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['invited'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['invited'])); $this->assertEquals(('server' === $this->getSide()), $webhook['data']['confirm']); } } diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php index 9e26322931..c2fd503c20 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomClientTest.php @@ -8,7 +8,8 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\ProjectCustom; use Tests\E2E\Scopes\SideClient; use Utopia\Database\DateTime; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\DatetimeValidator; class WebhooksCustomClientTest extends Scope { @@ -60,7 +61,7 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id']), true); $this->assertNotEmpty($webhook['data']['$id']); $this->assertEquals($webhook['data']['name'], $name); - $this->assertEquals(true, DateTime::isValid($webhook['data']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['registration'])); $this->assertEquals($webhook['data']['status'], true); $this->assertEquals($webhook['data']['email'], $email); $this->assertEquals($webhook['data']['emailVerification'], false); @@ -136,7 +137,7 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); $this->assertNotEmpty($webhook['data']['$id']); $this->assertEquals($webhook['data']['name'], $name); - $this->assertEquals(true, DateTime::isValid($webhook['data']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['registration'])); $this->assertEquals($webhook['data']['status'], false); $this->assertEquals($webhook['data']['email'], $email); $this->assertEquals($webhook['data']['emailVerification'], false); @@ -196,7 +197,7 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id']), true); $this->assertNotEmpty($webhook['data']['$id']); $this->assertNotEmpty($webhook['data']['userId']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['expire'])); $this->assertEquals($webhook['data']['ip'], '127.0.0.1'); $this->assertNotEmpty($webhook['data']['osCode']); $this->assertIsString($webhook['data']['osCode']); @@ -371,7 +372,7 @@ class WebhooksCustomClientTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); $this->assertNotEmpty($webhook['data']['$id']); $this->assertNotEmpty($webhook['data']['userId']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['expire'])); $this->assertEquals($webhook['data']['ip'], '127.0.0.1'); $this->assertNotEmpty($webhook['data']['osCode']); $this->assertIsString($webhook['data']['osCode']); @@ -683,7 +684,7 @@ class WebhooksCustomClientTest extends Scope $this->assertNotEmpty($webhook['data']['$id']); $this->assertNotEmpty($webhook['data']['userId']); $this->assertNotEmpty($webhook['data']['secret']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['expire'])); $data['secret'] = $webhook['data']['secret']; @@ -743,7 +744,7 @@ class WebhooksCustomClientTest extends Scope $this->assertNotEmpty($webhook['data']['$id']); $this->assertNotEmpty($webhook['data']['userId']); $this->assertNotEmpty($webhook['data']['secret']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['expire'])); $data['secret'] = $webhook['data']['secret']; @@ -799,7 +800,7 @@ class WebhooksCustomClientTest extends Scope $this->assertNotEmpty($webhook['data']['$id']); $this->assertNotEmpty($webhook['data']['userId']); $this->assertNotEmpty($webhook['data']['secret']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['expire'])); $data['secret'] = $webhook['data']['secret']; @@ -857,7 +858,7 @@ class WebhooksCustomClientTest extends Scope $this->assertNotEmpty($webhook['data']['$id']); $this->assertNotEmpty($webhook['data']['userId']); $this->assertNotEmpty($webhook['data']['secret']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['expire'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['expire'])); $data['secret'] = $webhook['data']['secret']; @@ -920,7 +921,7 @@ class WebhooksCustomClientTest extends Scope $this->assertNotEmpty($webhook['data']['userId']); $this->assertNotEmpty($webhook['data']['teamId']); $this->assertCount(2, $webhook['data']['roles']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['joined'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['joined'])); $this->assertEquals(true, $webhook['data']['confirm']); /** diff --git a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php index f2f4b27260..c20cb58f46 100644 --- a/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php +++ b/tests/e2e/Services/Webhooks/WebhooksCustomServerTest.php @@ -9,9 +9,10 @@ use Tests\E2E\Scopes\Scope; use Tests\E2E\Scopes\SideServer; use Utopia\CLI\Console; use Utopia\Database\DateTime; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; +use Utopia\Database\Validator\DatetimeValidator; class WebhooksCustomServerTest extends Scope { @@ -245,7 +246,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); $this->assertNotEmpty($webhook['data']['$id']); $this->assertEquals($webhook['data']['name'], $name); - $this->assertEquals(true, DateTime::isValid($webhook['data']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['registration'])); $this->assertEquals($webhook['data']['status'], true); $this->assertEquals($webhook['data']['email'], $email); $this->assertEquals($webhook['data']['emailVerification'], false); @@ -336,7 +337,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); $this->assertNotEmpty($webhook['data']['$id']); $this->assertEquals($webhook['data']['name'], $data['name']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['registration'])); $this->assertEquals($webhook['data']['status'], false); $this->assertEquals($webhook['data']['email'], $data['email']); $this->assertEquals($webhook['data']['emailVerification'], false); @@ -378,7 +379,7 @@ class WebhooksCustomServerTest extends Scope $this->assertEquals(empty($webhook['headers']['X-Appwrite-Webhook-User-Id'] ?? ''), ('server' === $this->getSide())); $this->assertNotEmpty($webhook['data']['$id']); $this->assertEquals($webhook['data']['name'], $data['name']); - $this->assertEquals(true, DateTime::isValid($webhook['data']['registration'])); + $this->assertEquals(true, (new DatetimeValidator())->isValid($webhook['data']['registration'])); $this->assertEquals($webhook['data']['status'], false); $this->assertEquals($webhook['data']['email'], $data['email']); $this->assertEquals($webhook['data']['emailVerification'], false); diff --git a/tests/resources/docker/docker-compose.yml b/tests/resources/docker/docker-compose.yml index 36bc43456c..6b0644c01e 100644 --- a/tests/resources/docker/docker-compose.yml +++ b/tests/resources/docker/docker-compose.yml @@ -63,7 +63,6 @@ services: - mariadb - redis # - clamav - - influxdb environment: - _APP_ENV - _APP_OPTIONS_ABUSE @@ -79,8 +78,6 @@ services: - _APP_DB_USER - _APP_DB_PASS - _APP_USAGE_STATS - - _APP_INFLUXDB_HOST - - _APP_INFLUXDB_PORT - _APP_STORAGE_ANTIVIRUS=disabled - _APP_STORAGE_LIMIT - _APP_FUNCTIONS_TIMEOUT @@ -100,13 +97,10 @@ services: - appwrite depends_on: - redis - - telegraf environment: - _APP_ENV - _APP_REDIS_HOST - _APP_REDIS_PORT - - _APP_STATSD_HOST - - _APP_STATSD_PORT appwrite-worker-audits: entrypoint: worker-audits @@ -368,21 +362,6 @@ services: # volumes: # - appwrite-uploads:/storage/uploads - influxdb: - image: influxdb:1.6 - container_name: appwrite-influxdb - restart: unless-stopped - networks: - - appwrite - volumes: - - appwrite-influxdb:/var/lib/influxdb:rw - - telegraf: - image: appwrite/telegraf:1.1.0 - container_name: appwrite-telegraf - restart: unless-stopped - networks: - - appwrite # redis-commander: # image: rediscommander/redis-commander:latest @@ -407,24 +386,6 @@ services: # - RESQUE_WEB_HTTP_BASIC_AUTH_USER=user # - RESQUE_WEB_HTTP_BASIC_AUTH_PASSWORD=password - # chronograf: - # image: chronograf:1.5 - # container_name: appwrite-chronograf - # restart: unless-stopped - # networks: - # - appwrite - # volumes: - # - appwrite-chronograf:/var/lib/chronograf - # ports: - # - "8888:8888" - # environment: - # - INFLUXDB_URL=http://influxdb:8086 - # - KAPACITOR_URL=http://kapacitor:9092 - # - AUTH_DURATION=48h - # - TOKEN_SECRET=duperduper5674829!jwt - # - GH_CLIENT_ID=d86f7145a41eacfc52cc - # - GH_CLIENT_SECRET=9e0081062367a2134e7f2ea95ba1a32d08b6c8ab - # - GH_ORGS=appwrite # webgrind: # image: 'jokkedk/webgrind:latest' @@ -444,6 +405,4 @@ volumes: appwrite-uploads: appwrite-certificates: appwrite-functions: - appwrite-influxdb: - appwrite-chronograf: appwrite-config: \ No newline at end of file diff --git a/tests/unit/Auth/AuthTest.php b/tests/unit/Auth/AuthTest.php index a4ed5740cb..c3c8e904d1 100644 --- a/tests/unit/Auth/AuthTest.php +++ b/tests/unit/Auth/AuthTest.php @@ -5,11 +5,10 @@ namespace Tests\Unit\Auth; use Appwrite\Auth\Auth; use Utopia\Database\DateTime; use Utopia\Database\Document; -use Utopia\Database\ID; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Role; use Utopia\Database\Validator\Authorization; use PHPUnit\Framework\TestCase; -use Utopia\Database\Database; use Utopia\Database\Validator\Roles; class AuthTest extends TestCase diff --git a/tests/unit/Docker/ComposeTest.php b/tests/unit/Docker/ComposeTest.php index e1677d570b..56448ffd01 100644 --- a/tests/unit/Docker/ComposeTest.php +++ b/tests/unit/Docker/ComposeTest.php @@ -28,7 +28,7 @@ class ComposeTest extends TestCase public function testServices(): void { - $this->assertCount(17, $this->object->getServices()); + $this->assertCount(15, $this->object->getServices()); $this->assertEquals('appwrite', $this->object->getService('appwrite')->getContainerName()); $this->assertEquals('', $this->object->getService('appwrite')->getImageVersion()); $this->assertEquals('2.2', $this->object->getService('traefik')->getImageVersion()); @@ -42,7 +42,7 @@ class ComposeTest extends TestCase public function testVolumes(): void { - $this->assertCount(9, $this->object->getVolumes()); + $this->assertCount(7, $this->object->getVolumes()); $this->assertEquals('appwrite-mariadb', $this->object->getVolumes()[0]); $this->assertEquals('appwrite-redis', $this->object->getVolumes()[1]); $this->assertEquals('appwrite-cache', $this->object->getVolumes()[2]); diff --git a/tests/unit/Messaging/MessagingChannelsTest.php b/tests/unit/Messaging/MessagingChannelsTest.php index 392f6d56fe..6fe7dda71f 100644 --- a/tests/unit/Messaging/MessagingChannelsTest.php +++ b/tests/unit/Messaging/MessagingChannelsTest.php @@ -6,8 +6,8 @@ use Appwrite\Auth\Auth; use Utopia\Database\Document; use Appwrite\Messaging\Adapter\Realtime; use PHPUnit\Framework\TestCase; -use Utopia\Database\ID; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Role; class MessagingChannelsTest extends TestCase { diff --git a/tests/unit/Messaging/MessagingGuestTest.php b/tests/unit/Messaging/MessagingGuestTest.php index d8ed58ad40..1aaa1febca 100644 --- a/tests/unit/Messaging/MessagingGuestTest.php +++ b/tests/unit/Messaging/MessagingGuestTest.php @@ -4,8 +4,8 @@ namespace Tests\Unit\Messaging; use Appwrite\Messaging\Adapter\Realtime; use PHPUnit\Framework\TestCase; -use Utopia\Database\ID; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Role; class MessagingGuestTest extends TestCase { diff --git a/tests/unit/Messaging/MessagingTest.php b/tests/unit/Messaging/MessagingTest.php index 0b7baf2631..c2e3971945 100644 --- a/tests/unit/Messaging/MessagingTest.php +++ b/tests/unit/Messaging/MessagingTest.php @@ -5,9 +5,9 @@ namespace Tests\Unit\Messaging; use Utopia\Database\Document; use Appwrite\Messaging\Adapter\Realtime; use PHPUnit\Framework\TestCase; -use Utopia\Database\ID; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\ID; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; class MessagingTest extends TestCase { diff --git a/tests/unit/Network/Validators/OriginTest.php b/tests/unit/Network/Validators/OriginTest.php index 2392ae4cfa..30d18ecaa9 100644 --- a/tests/unit/Network/Validators/OriginTest.php +++ b/tests/unit/Network/Validators/OriginTest.php @@ -4,7 +4,7 @@ namespace Tests\Unit\Network\Validators; use Appwrite\Network\Validator\Origin; use PHPUnit\Framework\TestCase; -use Utopia\Database\ID; +use Utopia\Database\Helpers\ID; class OriginTest extends TestCase { diff --git a/tests/unit/Utopia/Response/Filters/V15Test.php b/tests/unit/Utopia/Response/Filters/V15Test.php index ce7870483c..fc38e5320b 100644 --- a/tests/unit/Utopia/Response/Filters/V15Test.php +++ b/tests/unit/Utopia/Response/Filters/V15Test.php @@ -4,10 +4,9 @@ namespace Tests\Unit\Utopia\Response\Filters; use Appwrite\Utopia\Response\Filters\V15; use Appwrite\Utopia\Response; -use Utopia\Database\Permission; -use Utopia\Database\Role; +use Utopia\Database\Helpers\Permission; +use Utopia\Database\Helpers\Role; use PHPUnit\Framework\TestCase; -use stdClass; class V15Test extends TestCase {