From 42f0bddd60c7afd4982043df667b17d5ee52d09e Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 15 Jul 2022 13:54:27 +0400 Subject: [PATCH] feat: merge and fix conflicts --- app/controllers/api/health.php | 5 +- app/realtime.php | 66 ++++---------------------- app/workers/databases.php | 4 ++ docker-compose.yml | 1 + src/Appwrite/Database/DatabasePool.php | 43 ++++++++++------- 5 files changed, 43 insertions(+), 76 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 57a579550..342bfa12a 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -64,7 +64,10 @@ App::get('/v1/health/db') $checkStart = \microtime(true); try { - $consoleDB = $utopia->getResource('consoleDB'); /* @var $db PDO */ + $dbPool = $utopia->getResource('dbPool'); + $name = $dbPool->getConsoleDB(); + /* @var $consoleDB PDO */ + $consoleDB = $dbPool->getPDO($name); // Run a small test to check the connection $statement = $consoleDB->prepare("SELECT 1;"); diff --git a/app/realtime.php b/app/realtime.php index db8661341..b3f9945bb 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -93,63 +93,15 @@ $logError = function (Throwable $error, string $action) use ($register) { $server->error($logError); -function getDatabase(Registry &$register, string $namespace) +function getDatabase(Registry &$register, string $projectID) { - $redis = $register->get('redisPool')->get(); - $cache = new Cache(new RedisCache($redis)); - - $consoleDB = $register->get('dbPool')->getConsoleDBFromPool(); - $db = $consoleDB; - $dbName = ''; - - if ($namespace != '_console') { - $cache = new Cache(new RedisCache($redis)); - $database = new Database(new MariaDB($consoleDB), $cache); - $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $database->setNamespace('_console'); // Main DB - - $project = $database->getDocument('projects', ltrim($namespace, '_')); - $dbName = $project->getAttribute('database', ''); - if (!empty($dbName)) { - $projectDB = $register->get('dbPool')->getDBFromPool($dbName); - $db = $projectDB; - } - } - - $attempts = 0; - - do { - try { - $attempts++; - - $database = new Database(new MariaDB($db), $cache); - $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $database->setNamespace($namespace); - - if (!$database->exists($database->getDefaultDatabase(), 'realtime')) { - throw new Exception('Collection not ready'); - } - - break; // leave loop if successful - } catch (\Throwable $e) { - Console::warning("Database not ready. Retrying connection ({$attempts})..."); - if ($attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS) { - throw new \Exception('Failed to connect to database: ' . $e->getMessage()); - } - sleep(DATABASE_RECONNECT_SLEEP); - } - } while ($attempts < DATABASE_RECONNECT_MAX_ATTEMPTS); + [$database, $returnDatabase] = $register->get('dbPool')->getDBFromPool($projectID, $redis); return [ $database, - function () use ($register, $db, $dbName, $redis) { - if (empty($dbName)) { - $register->get('dbPool')->putConsoleDb($db); - } else { - $register->get('dbPool')->put($db, $dbName); - } - + function () use ($register, $returnDatabase, $redis) { + call_user_func($returnDatabase); $register->get('redisPool')->put($redis); } ]; @@ -164,7 +116,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume */ go(function () use ($register, $containerId, &$statsDocument) { $attempts = 0; - [$database, $returnDatabase] = getDatabase($register, '_console'); + [$database, $returnDatabase] = getDatabase($register, 'console'); do { try { $attempts++; @@ -201,7 +153,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume } try { - [$database, $returnDatabase] = getDatabase($register, '_console'); + [$database, $returnDatabase] = getDatabase($register, 'console'); $statsDocument ->setAttribute('timestamp', time()) @@ -227,7 +179,7 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, * Sending current connections to project channels on the console project every 5 seconds. */ if ($realtime->hasSubscriber('console', 'role:member', 'project')) { - [$database, $returnDatabase] = getDatabase($register, '_console'); + [$database, $returnDatabase] = getDatabase($register, 'console'); $payload = []; @@ -327,9 +279,9 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, if ($realtime->hasSubscriber($projectId, 'user:' . $userId)) { $connection = array_key_first(reset($realtime->subscriptions[$projectId]['user:' . $userId])); - [$consoleDatabase, $returnConsoleDatabase] = getDatabase($register, '_console'); + [$consoleDatabase, $returnConsoleDatabase] = getDatabase($register, 'console'); $project = Authorization::skip(fn() => $consoleDatabase->getDocument('projects', $projectId)); - [$database, $returnDatabase] = getDatabase($register, "_{$project->getInternalId()}"); + [$database, $returnDatabase] = getDatabase($register, $project->getId()); $user = $database->getDocument('users', $userId); diff --git a/app/workers/databases.php b/app/workers/databases.php index 71e78b377..63b41e4e9 100644 --- a/app/workers/databases.php +++ b/app/workers/databases.php @@ -77,6 +77,8 @@ class DatabaseV1 extends Worker * Fetch attribute from the database, since with Resque float values are loosing informations. */ $attribute = $dbForProject->getDocument('attributes', $attribute->getId()); + var_dump($attribute); + var_dump($attribute->getId()); $collectionId = $collection->getId(); $key = $attribute->getAttribute('key', ''); @@ -97,6 +99,8 @@ class DatabaseV1 extends Worker } $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available')); } catch (\Throwable $th) { + var_dump($th->getTraceAsString()); + var_dump($attribute->getArrayCopy()); Console::error($th->getMessage()); $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'failed')); } finally { diff --git a/docker-compose.yml b/docker-compose.yml index 4b588409e..8ed78a567 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -318,6 +318,7 @@ 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 diff --git a/src/Appwrite/Database/DatabasePool.php b/src/Appwrite/Database/DatabasePool.php index 78e240bb1..11ce60e57 100644 --- a/src/Appwrite/Database/DatabasePool.php +++ b/src/Appwrite/Database/DatabasePool.php @@ -72,6 +72,11 @@ class DatabasePool { ->withPassword($dsn->getPassword()) ->withOptions([ PDO::ATTR_ERRMODE => App::isDevelopment() ? PDO::ERRMODE_WARNING : PDO::ERRMODE_SILENT, // If in production mode, warnings are not displayed + PDO::ATTR_TIMEOUT => 3, // Seconds + PDO::ATTR_PERSISTENT => true, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => true, + PDO::ATTR_STRINGIFY_FETCHES => true ]), 64 ); @@ -86,7 +91,7 @@ class DatabasePool { * @param string $name * @return ?PDO */ - private function getPDO(string $name): ?PDO + public function getPDO(string $name): ?PDO { $dsn = $this->dsns[$name] ?? throw new Exception("Database with name : $name not found.", 500); @@ -125,8 +130,9 @@ class DatabasePool { $cache = new Cache(new RedisCache($redis)); $database = new Database(new MariaDB($pdo), $cache); $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $database->setNamespace("_console"); - + $namespace = "_project_console"; + $database->setNamespace($namespace); + $project = Authorization::skip(fn() => $database->getDocument('projects', $projectID)); $internalID = $project->getInternalId(); $database = $project->getAttribute('database', ''); @@ -141,7 +147,7 @@ class DatabasePool { * * @return ?Database */ - public function getDB(string $projectID, \Redis $redis): ?Database + public function getDB(string $projectID, ?\Redis $redis): ?Database { /** Get DB name from the console database */ [$name, $internalID] = $this->getName($projectID, $redis); @@ -155,7 +161,8 @@ class DatabasePool { $cache = new Cache(new RedisCache($redis)); $database = new Database(new MariaDB($pdo), $cache); $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - $database->setNamespace("_{$internalID}"); + $namespace = "_project_$internalID"; + $database->setNamespace($namespace); return $database; } @@ -179,7 +186,7 @@ class DatabasePool { [$name, $internalID] = $this->getName($projectID, $redis); $pool = $this->pools[$name] ?? throw new Exception("Database pool with name : $name not found. Check the value of _APP_PROJECT_DB in .env", 500); - $namespace = "_$internalID"; + $namespace = "_project_$internalID"; $attempts = 0; do { try { @@ -273,19 +280,19 @@ class DatabasePool { // * Convenience methods for console DB // */ - // /** - // * Function to get a single instace of the console DB - // * - // * @return ?PDO - // */ - // public function getConsoleDB(): ?PDO - // { - // if (empty($this->consoleDB)) { - // throw new Exception('Console DB is not defined', 500); - // }; + /** + * Function to get the name of the console DB + * + * @return ?string + */ + public function getConsoleDB(): ?string + { + if (empty($this->consoleDB)) { + throw new Exception('Console DB is not defined', 500); + }; - // return $this->getDB($this->consoleDB); - // } + return $this->consoleDB; + } // /** // * Function to get an instance of the console DB from the database pool