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 + + + +WebWebFlutterFlutteriOSiOSAndroidAndroidServersServersAppwriteAppwriteLoadbalancerLoadbalancerREST APIREST APIQueue(Redis)Queue...Cache(Redis)Cache...DatabaseDatabaseUsersUsersAccountAccountTeamsTeamsDatabaseDatabaseStorageStorageLocalizationLocalizationAvatarsAvatarsHealthHealthSSL GatewaySSL GatewayMaintenanceMaintenanceSecurity LayerSecurity LayerUsageUsageAuditsAuditsMailsMailsSMTPSMTPDatabaseDatabaseWebhooksWebhooksFunctionsFunctionsCertsCertsDeletesDeletesLetsencryptLetsencryptAntiVirus(ClamAV)AntiVirus...Realtime APIRealtime APISchedulerSchedulerBuildsBuildsExecutor(Open-Runtimes)Executor...Docker / K8SDocker / K8SConsoleConsoleFunctionsFunctionsGraphQL 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 {