diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 3f29a0acf1..81e48a22ff 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -120,8 +120,7 @@ App::post('/v1/projects') 'database' => $pdo->getName() ])); - $dbForProject = DatabasePool::getDatabase($pdo->getConnection(), $cache); - $dbForProject->setNamespace("_{$project->getInternalId()}"); + $dbForProject = DatabasePool::getDatabase($pdo->getConnection(), $cache, "_{$project->getInternalId()}"); $dbForProject->create(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); $audit = new Audit($dbForProject); diff --git a/app/init.php b/app/init.php index 2c71f9fc2a..c26ebe1854 100644 --- a/app/init.php +++ b/app/init.php @@ -867,16 +867,14 @@ App::setResource('dbForProject', function ($dbPool, $cache, Document $project) { $database = $dbPool->getConsoleDB(); } $pdo = $dbPool->getPDOFromPool($database); - $database = DatabasePool::getDatabase($pdo->getConnection(), $cache); - $database->setNamespace("_{$project->getInternalId()}"); + $database = DatabasePool::getDatabase($pdo->getConnection(), $cache, "_{$project->getInternalId()}"); return $database; }, ['dbPool', 'cache', 'project']); App::setResource('dbForConsole', function ($dbPool, $cache) { $database = $dbPool->getConsoleDB(); $pdo = $dbPool->getPDOFromPool($database); - $database = DatabasePool::getDatabase($pdo->getConnection(), $cache); - $database->setNamespace('_console'); + $database = DatabasePool::getDatabase($pdo->getConnection(), $cache, '_console'); return $database; }, ['dbPool', 'cache']); diff --git a/app/realtime.php b/app/realtime.php index 6ea270c054..1557180fb3 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -101,15 +101,13 @@ function getDatabase(Registry &$register, string $projectId) /** Get the console DB */ $database = $dbPool->getConsoleDB(); $pdo = $dbPool->getPDOFromPool($database); - $database = DatabasePool::getDatabase($pdo->getConnection(), $redis); - $database->setNamespace("_console"); + $database = DatabasePool::getDatabase($pdo->getConnection(), $redis, '_console'); if ($projectId !== 'console') { $project = Authorization::skip(fn() => $database->getDocument('projects', $projectId)); $database = $project->getAttribute('database', ''); $pdo = $dbPool->getPDOFromPool($database); - $database = DatabasePool::getDatabase($pdo->getConnection(), $redis); - $database->setNamespace("_{$project->getInternalId()}"); + $database = DatabasePool::getDatabase($pdo->getConnection(), $redis, "_{$project->getInternalId()}"); } return [ @@ -477,15 +475,13 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re /** Get the console DB */ $database = $dbPool->getConsoleDB(); $pdo = $dbPool->getPDOFromPool($database); - $database = DatabasePool::getDatabase($pdo->getConnection(), $redis); - $database->setNamespace("_console"); + $database = DatabasePool::getDatabase($pdo->getConnection(), $redis, '_console'); if ($projectId !== 'console') { $project = Authorization::skip(fn() => $database->getDocument('projects', $projectId)); $database = $project->getAttribute('database', ''); $pdo = $dbPool->getPDOFromPool($database); - $database = DatabasePool::getDatabase($pdo->getConnection(), $redis); - $database->setNamespace("_{$project->getInternalId()}"); + $database = DatabasePool::getDatabase($pdo->getConnection(), $redis, "_{$project->getInternalId()}"); } /* diff --git a/app/tasks/doctor.php b/app/tasks/doctor.php index c937884be5..634381ba41 100644 --- a/app/tasks/doctor.php +++ b/app/tasks/doctor.php @@ -96,7 +96,9 @@ $cli } try { - $register->get('dbPool')->getConsoleDB(); /* @var $db PDO */ + $dbPool = $register->get('dbPool'); /* @var $dbPool DatabasePool */ + $database = $dbPool->getConsoleDB(); + $pdo = $dbPool->getPDO($database); Console::success('Database............connected 👍'); } catch (\Throwable $th) { Console::error('Database.........disconnected 👎'); diff --git a/app/tasks/usage.php b/app/tasks/usage.php index 6f145aef8d..e7237ad221 100644 --- a/app/tasks/usage.php +++ b/app/tasks/usage.php @@ -2,6 +2,7 @@ global $cli, $register; +use Appwrite\Database\DatabasePool; use Appwrite\Stats\Usage; use Appwrite\Stats\UsageDB; use InfluxDB\Database as InfluxDatabase; @@ -27,8 +28,8 @@ function getDatabase(Registry &$register): Database do { try { $attempts++; - $database = $dbPool->getDB($database, $redis); - $database->setNamespace('_console'); + $pdo = $dbPool->getPDO($database); + $database = DatabasePool::getDatabase($pdo, $redis, '_console'); if (!$database->exists($database->getDefaultDatabase(), 'projects')) { throw new Exception('Projects collection not ready'); diff --git a/src/Appwrite/Database/DatabasePool.php b/src/Appwrite/Database/DatabasePool.php index bb09c2df6a..ebd6a883c9 100644 --- a/src/Appwrite/Database/DatabasePool.php +++ b/src/Appwrite/Database/DatabasePool.php @@ -14,6 +14,7 @@ use Appwrite\Database\PDOPool; use Swoole\Database\PDOConfig; use Utopia\Database\Adapter\MariaDB; use Utopia\Cache\Adapter\Redis as RedisCache; +use Utopia\CLI\Console; class DatabasePool { @@ -113,21 +114,6 @@ class DatabasePool return $pdo; } - /** - * Function to get a single PDO instance for a project - * - * @param string $projectId - * - * @return ?Database - */ - public function getDB(string $database, ?\Redis $redis): ?Database - { - /** Get a PDO instance using the database name */ - $pdo = $this->getPDO($database); - $database = self::getDatabase($pdo, $redis); - return $database; - } - /** * Get a PDO instance from the list of available database pools. Meant to be used in co-routines * @@ -193,30 +179,26 @@ class DatabasePool return $this->consoleDB; } - public static function wait() + public static function wait(Database $database, string $collection) { - // $namespace = "_$internalID"; - // $attempts = 0; - // do { - // try { - // $attempts++; - // $pdo = $pool->get(); - // $database = $this->getDatabase($pdo, $redis); - // $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); - // $database->setNamespace($namespace); + $attempts = 0; + do { + try { + $attempts++; + if (!$database->exists($database->getDefaultDatabase(), $collection)) { + throw new Exception('Collection not ready'); + } + break; // leave loop if successful + } catch (\Exception $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); - // // if (!$database->exists($database->getDefaultDatabase(), 'metadata')) { - // // throw new Exception('Collection not ready'); - // // } - // break; // leave loop if successful - // } catch (\Exception $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); + return $database; } /** @@ -224,14 +206,16 @@ class DatabasePool * * @param PDO|PDOProxy $pdo * @param \Redis $redis + * @param string $namespace * * @return Database */ - public static function getDatabase(PDO|PDOProxy $pdo, \Redis $redis): Database + public static function getDatabase(PDO|PDOProxy $pdo, \Redis $redis, string $namespace = ''): Database { $cache = new Cache(new RedisCache($redis)); $database = new Database(new MariaDB($pdo), $cache); $database->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite')); + $database->setNamespace($namespace); return $database; } } diff --git a/src/Appwrite/Resque/Worker.php b/src/Appwrite/Resque/Worker.php index df7863d593..e9ddc1f7c6 100644 --- a/src/Appwrite/Resque/Worker.php +++ b/src/Appwrite/Resque/Worker.php @@ -2,6 +2,7 @@ namespace Appwrite\Resque; +use Appwrite\Database\DatabasePool; use Utopia\App; use Utopia\Cache\Cache; use Utopia\Cache\Adapter\Redis as RedisCache; @@ -177,10 +178,9 @@ abstract class Worker $cache = $register->get('cache'); $dbPool = $register->get('dbPool'); - - $dbForProject = $dbPool->getDB($database, $cache); $namespace = "_$internalId"; - $dbForProject->setNamespace($namespace); + $pdo = $dbPool->getPDO($database); + $dbForProject = DatabasePool::getDatabase($pdo, $cache, $namespace); return $dbForProject; } @@ -199,9 +199,9 @@ abstract class Worker throw new \Exception('Database name not provided - cannot get database'); } - $dbForConsole = $dbPool->getDB($database, $cache); $namespace = "_console"; - $dbForConsole->setNamespace($namespace); + $pdo = $dbPool->getPDO($database); + $dbForConsole = DatabasePool::getDatabase($pdo, $cache, $namespace); return $dbForConsole; }