From db940701628217463ec8523ccbb6b2889968b803 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 6 May 2024 17:33:36 +1200 Subject: [PATCH] Use DSN for project database --- app/cli.php | 13 ++++++----- app/controllers/api/projects.php | 37 +++++++++++++++++++++++--------- app/init.php | 15 +++++++------ app/realtime.php | 17 +++++++++------ app/worker.php | 18 ++++++++++------ composer.json | 2 +- composer.lock | 18 +++++++++------- docker-compose.yml | 3 +-- 8 files changed, 77 insertions(+), 46 deletions(-) diff --git a/app/cli.php b/app/cli.php index 11ab6598d9..73da58bcbf 100644 --- a/app/cli.php +++ b/app/cli.php @@ -16,6 +16,7 @@ use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Service; use Utopia\Pools\Group; @@ -99,16 +100,18 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $dbForConsole; } - $databaseName = $project->getAttribute('database'); + $dsn = new DSN($project->getAttribute('database')); + + $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) @@ -128,11 +131,11 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, $databases[$databaseName] = $database; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index d3d09f4adf..0770723f96 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -30,6 +30,7 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Database\Validator\UID; use Utopia\Domains\Validator\PublicDomain; +use Utopia\DSN\DSN; use Utopia\Locale\Locale; use Utopia\Pools\Group; use Utopia\System\System; @@ -142,9 +143,9 @@ App::post('/v1/projects') $databaseOverride = App::getEnv('_APP_DATABASE_OVERRIDE'); $index = \array_search($databaseOverride, $databases); if ($index !== false) { - $database = $databases[$index]; + $dsn = $databases[$index]; } else { - $database = $databases[array_rand($databases)]; + $dsn = $databases[array_rand($databases)]; } if ($projectId === 'console') { @@ -156,7 +157,14 @@ App::post('/v1/projects') !\mt_rand(0, 19) && App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' ) { - $database = DATABASE_SHARED_TABLES; + $schema = 'appwrite'; + $database = 'appwrite'; + $namespace = App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); + $dsn = $schema . '://' . DATABASE_SHARED_TABLES . '?database=' . $database; + + if (!empty($namespace)) { + $dsn .= '&namespace=' . $namespace; + } } // TODO: Allow overriding in development mode. Temporary until all projects are using shared tables. @@ -165,7 +173,14 @@ App::post('/v1/projects') && App::getEnv('_APP_EDITION', 'self-hosted') !== 'self-hosted' && $request->getHeader('x-appwrite-share-tables', false) ) { - $database = DATABASE_SHARED_TABLES; + $schema = 'appwrite'; + $database = 'appwrite'; + $namespace = App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); + $dsn = $schema . '://' . DATABASE_SHARED_TABLES . '?database=' . $database; + + if (!empty($namespace)) { + $dsn .= '&namespace=' . $namespace; + } } try { @@ -199,19 +214,21 @@ App::post('/v1/projects') 'keys' => null, 'auths' => $auths, 'search' => implode(' ', [$projectId, $name]), - 'database' => $database, + 'database' => $dsn, ])); } catch (Duplicate) { throw new Exception(Exception::PROJECT_ALREADY_EXISTS); } - $dbForProject = new Database($pools->get($database)->pop()->getResource(), $cache); + $dsn = new DSN($dsn); + $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); + $dbForProject = new Database($pools->get($databaseName)->pop()->getResource(), $cache); - if ($database === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $dbForProject ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $dbForProject ->setSharedTables(false) @@ -224,8 +241,8 @@ App::post('/v1/projects') $audit = new Audit($dbForProject); $audit->setup(); - $adapter = new TimeLimit('', 0, 1, $dbForProject); - $adapter->setup(); + $abuse = new TimeLimit('', 0, 1, $dbForProject); + $abuse->setup(); /** @var array $collections */ $collections = Config::getParam('collections', [])['projects'] ?? []; diff --git a/app/init.php b/app/init.php index 2e9af63d5d..0412052294 100644 --- a/app/init.php +++ b/app/init.php @@ -1314,11 +1314,13 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole, ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + $dsn = new DSN($project->getAttribute('database')); + + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) @@ -1354,19 +1356,20 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole, return $dbForConsole; } - $databaseName = $project->getAttribute('database'); + $dsn = new DSN($project->getAttribute('database')); + $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); - $configure = (function (Database $database) use ($project) { + $configure = (function (Database $database) use ($project, $dsn) { $database ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) diff --git a/app/realtime.php b/app/realtime.php index c58a32ded7..489d0d9642 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -26,6 +26,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; +use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\System\System; use Utopia\WebSocket\Adapter; @@ -77,19 +78,21 @@ if (!function_exists("getProjectDB")) { return getConsoleDB(); } - $dbAdapter = $pools - ->get($project->getAttribute('database')) + $dsn = new DSN($project->getAttribute('database')); + $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); + + $adapter = $pools + ->get($databaseName) ->pop() - ->getResource() - ; + ->getResource(); - $database = new Database($dbAdapter, getCache()); + $database = new Database($adapter, getCache()); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) diff --git a/app/worker.php b/app/worker.php index 8167289e4a..9ab41bacb5 100644 --- a/app/worker.php +++ b/app/worker.php @@ -25,6 +25,7 @@ use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; +use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Logger\Logger; use Utopia\Platform\Service; @@ -79,11 +80,13 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $database = new Database($adapter, $cache); - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + $dsn = new DSN($project->getAttribute('database')); + + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) @@ -102,16 +105,17 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso return $dbForConsole; } - $databaseName = $project->getAttribute('database'); + $dsn = new DSN($project->getAttribute('database')); + $databaseName = empty($dsn->getHost()) ? $dsn->getPath() : $dsn->getHost(); if (isset($databases[$databaseName])) { $database = $databases[$databaseName]; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) @@ -131,11 +135,11 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso $databases[$databaseName] = $database; - if ($project->getAttribute('database') === DATABASE_SHARED_TABLES) { + if ($dsn->getHost() === DATABASE_SHARED_TABLES) { $database ->setSharedTables(true) ->setTenant($project->getInternalId()) - ->setNamespace(App::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '')); + ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) diff --git a/composer.json b/composer.json index df004e6b44..5ce9a0a138 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "utopia-php/config": "0.2.*", "utopia-php/database": "0.49.*", "utopia-php/domains": "0.5.*", - "utopia-php/dsn": "0.2.*", + "utopia-php/dsn": "dev-feat-allow-nullable-scheme", "utopia-php/framework": "0.33.*", "utopia-php/fetch": "0.2.*", "utopia-php/image": "0.6.*", diff --git a/composer.lock b/composer.lock index 9d4300f0a4..cd47546770 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": "28ecd4705def24ce61eee0f6676439d6", + "content-hash": "7276ce4fa8a3c75f95f952153fdca69f", "packages": [ { "name": "adhocore/jwt", @@ -1672,16 +1672,16 @@ }, { "name": "utopia-php/dsn", - "version": "0.2.0", + "version": "dev-feat-allow-nullable-scheme", "source": { "type": "git", "url": "https://github.com/utopia-php/dsn.git", - "reference": "c11f37a12c3f6aaf9fea97ca7cb363dcc93668d7" + "reference": "09521c1fb6dc5488df5e89eeb6b3ca5e736fd97c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/dsn/zipball/c11f37a12c3f6aaf9fea97ca7cb363dcc93668d7", - "reference": "c11f37a12c3f6aaf9fea97ca7cb363dcc93668d7", + "url": "https://api.github.com/repos/utopia-php/dsn/zipball/09521c1fb6dc5488df5e89eeb6b3ca5e736fd97c", + "reference": "09521c1fb6dc5488df5e89eeb6b3ca5e736fd97c", "shasum": "" }, "require": { @@ -1713,9 +1713,9 @@ ], "support": { "issues": "https://github.com/utopia-php/dsn/issues", - "source": "https://github.com/utopia-php/dsn/tree/0.2.0" + "source": "https://github.com/utopia-php/dsn/tree/feat-allow-nullable-scheme" }, - "time": "2023-11-02T12:01:43+00:00" + "time": "2024-05-06T05:15:19+00:00" }, { "name": "utopia-php/fetch", @@ -5505,7 +5505,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/dsn": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docker-compose.yml b/docker-compose.yml index 0f78f08d36..82c38ba269 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,8 +10,6 @@ x-logging: &x-logging max-file: "5" max-size: "10m" -version: "3" - services: traefik: image: traefik:2.11 @@ -94,6 +92,7 @@ services: - app/http.php environment: - _APP_ENV + - _APP_EDITION - _APP_WORKER_PER_CORE - _APP_LOCALE - _APP_CONSOLE_WHITELIST_ROOT