appwrite/app/cli.php

268 lines
8.6 KiB
PHP
Raw Normal View History

2020-07-28 19:48:51 +00:00
<?php
2022-05-23 14:54:50 +00:00
require_once __DIR__ . '/init.php';
2020-07-28 19:48:51 +00:00
2022-12-13 11:16:12 +00:00
use Appwrite\Event\Certificate;
2024-03-06 17:34:21 +00:00
use Appwrite\Event\Delete;
2022-11-15 18:13:17 +00:00
use Appwrite\Event\Func;
2025-01-30 04:07:44 +00:00
use Appwrite\Event\StatsResources;
2025-01-30 04:53:53 +00:00
use Appwrite\Event\StatsUsage;
2022-11-14 10:29:10 +00:00
use Appwrite\Platform\Appwrite;
use Appwrite\Runtimes\Runtimes;
2024-10-08 07:54:40 +00:00
use Utopia\Cache\Adapter\Sharding;
use Utopia\Cache\Cache;
use Utopia\CLI\CLI;
2024-03-06 17:34:21 +00:00
use Utopia\CLI\Console;
2022-11-14 10:46:11 +00:00
use Utopia\Config\Config;
2024-10-08 07:54:40 +00:00
use Utopia\Database\Database;
use Utopia\Database\Document;
2024-03-06 17:34:21 +00:00
use Utopia\Database\Validator\Authorization;
2024-10-08 07:54:40 +00:00
use Utopia\DSN\DSN;
2022-10-28 08:56:45 +00:00
use Utopia\Logger\Log;
2024-03-06 17:34:21 +00:00
use Utopia\Platform\Service;
2024-10-08 07:54:40 +00:00
use Utopia\Pools\Group;
2025-01-29 14:13:58 +00:00
use Utopia\Queue\Publisher;
2022-10-28 08:49:05 +00:00
use Utopia\Registry\Registry;
2024-04-01 11:02:47 +00:00
use Utopia\System\System;
2022-04-10 09:38:22 +00:00
// overwriting runtimes to be architectur agnostic for CLI
2025-03-11 17:19:25 +00:00
Config::setParam('runtimes', (new Runtimes('v5'))->getAll(supported: false));
// require controllers after overwriting runtimes
require_once __DIR__ . '/controllers/general.php';
2024-10-08 07:54:40 +00:00
Authorization::disable();
CLI::setResource('register', fn () => $register);
CLI::setResource('cache', function ($pools) {
$list = Config::getParam('pools-cache', []);
$adapters = [];
foreach ($list as $value) {
$adapters[] = $pools
->get($value)
->pop()
->getResource()
;
}
return new Cache(new Sharding($adapters));
}, ['pools']);
CLI::setResource('pools', function (Registry $register) {
return $register->get('pools');
}, ['register']);
CLI::setResource('dbForPlatform', function ($pools, $cache) {
2024-10-08 07:54:40 +00:00
$sleep = 3;
$maxAttempts = 5;
$attempts = 0;
$ready = false;
do {
$attempts++;
try {
// Prepare database connection
$dbAdapter = $pools
->get('console')
->pop()
->getResource();
$dbForPlatform = new Database($dbAdapter, $cache);
2024-10-08 07:54:40 +00:00
$dbForPlatform
2024-10-08 07:54:40 +00:00
->setNamespace('_console')
->setMetadata('host', \gethostname())
->setMetadata('project', 'console');
// Ensure tables exist
$collections = Config::getParam('collections', [])['console'];
$last = \array_key_last($collections);
if (!($dbForPlatform->exists($dbForPlatform->getDatabase(), $last))) { /** TODO cache ready variable using registry */
2024-10-08 07:54:40 +00:00
throw new Exception('Tables not ready yet.');
}
2022-10-28 08:56:45 +00:00
2024-10-08 07:54:40 +00:00
$ready = true;
} catch (\Throwable $err) {
Console::warning($err->getMessage());
$pools->get('console')->reclaim();
sleep($sleep);
}
} while ($attempts < $maxAttempts && !$ready);
if (!$ready) {
throw new Exception("Console is not ready yet. Please try again later.");
}
return $dbForPlatform;
2024-10-08 07:54:40 +00:00
}, ['pools', 'cache']);
CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) {
2024-10-08 07:54:40 +00:00
$databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools
return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) {
2024-10-08 07:54:40 +00:00
if ($project->isEmpty() || $project->getId() === 'console') {
return $dbForPlatform;
2024-10-08 07:54:40 +00:00
}
try {
$dsn = new DSN($project->getAttribute('database'));
} catch (\InvalidArgumentException) {
// TODO: Temporary until all projects are using shared tables
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}
if (isset($databases[$dsn->getHost()])) {
$database = $databases[$dsn->getHost()];
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
2024-10-08 07:54:40 +00:00
if (\in_array($dsn->getHost(), $sharedTables)) {
2024-10-08 07:54:40 +00:00
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
2024-10-01 14:30:47 +00:00
}
2022-10-28 08:56:45 +00:00
2024-10-08 07:54:40 +00:00
return $database;
}
$dbAdapter = $pools
->get($dsn->getHost())
->pop()
->getResource();
$database = new Database($dbAdapter, $cache);
$databases[$dsn->getHost()] = $database;
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
2024-10-08 07:54:40 +00:00
if (\in_array($dsn->getHost(), $sharedTables)) {
2024-10-08 07:54:40 +00:00
$database
->setSharedTables(true)
->setTenant($project->getInternalId())
->setNamespace($dsn->getParam('namespace'));
} else {
$database
->setSharedTables(false)
->setTenant(null)
->setNamespace('_' . $project->getInternalId());
}
$database
->setMetadata('host', \gethostname())
->setMetadata('project', $project->getId());
return $database;
};
}, ['pools', 'dbForPlatform', 'cache']);
2024-10-08 07:54:40 +00:00
2025-01-27 02:26:06 +00:00
CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) {
$database = null;
return function (?Document $project = null) use ($pools, $cache, $database) {
if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant($project->getInternalId());
return $database;
}
$dbAdapter = $pools
->get('logs')
->pop()
->getResource();
$database = new Database(
$dbAdapter,
$cache
);
$database
->setSharedTables(true)
->setNamespace('logsV1')
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
// set tenant
if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') {
$database->setTenant($project->getInternalId());
}
return $database;
};
}, ['pools', 'cache']);
CLI::setResource('queueForStatsUsage', function (Connection $publisher) {
return new StatsUsage($publisher);
}, ['publisher']);
CLI::setResource('queueForStatsResources', function (Publisher $publisher) {
return new StatsResources($publisher);
}, ['publisher']);
2025-01-29 14:13:58 +00:00
CLI::setResource('publisher', function (Group $pools) {
return $pools->get('publisher')->pop()->getResource();
2024-10-08 07:54:40 +00:00
}, ['pools']);
2025-01-29 14:13:58 +00:00
CLI::setResource('queueForFunctions', function (Publisher $publisher) {
return new Func($publisher);
}, ['publisher']);
CLI::setResource('queueForDeletes', function (Publisher $publisher) {
return new Delete($publisher);
}, ['publisher']);
CLI::setResource('queueForCertificates', function (Publisher $publisher) {
return new Certificate($publisher);
}, ['publisher']);
2024-10-08 07:54:40 +00:00
CLI::setResource('logError', function (Registry $register) {
return function (Throwable $error, string $namespace, string $action) use ($register) {
$logger = $register->get('logger');
if ($logger) {
$version = System::getEnv('_APP_VERSION', 'UNKNOWN');
$log = new Log();
$log->setNamespace($namespace);
2024-11-26 13:54:27 +00:00
$log->setServer(System::getEnv('_APP_LOGGING_SERVICE_IDENTIFIER', \gethostname()));
2024-10-08 07:54:40 +00:00
$log->setVersion($version);
$log->setType(Log::TYPE_ERROR);
$log->setMessage($error->getMessage());
$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->setAction($action);
$isProduction = System::getEnv('_APP_ENV', 'development') === 'production';
$log->setEnvironment($isProduction ? Log::ENVIRONMENT_PRODUCTION : Log::ENVIRONMENT_STAGING);
try {
$responseCode = $logger->addLog($log);
Console::info('Error log pushed with status code: ' . $responseCode);
} catch (Throwable $th) {
Console::error('Error pushing log: ' . $th->getMessage());
}
}
2024-10-01 14:30:47 +00:00
2024-10-08 07:54:40 +00:00
Console::warning("Failed: {$error->getMessage()}");
Console::warning($error->getTraceAsString());
};
}, ['register']);
2022-10-28 08:56:45 +00:00
2022-11-14 10:29:10 +00:00
$platform = new Appwrite();
2024-10-08 07:54:40 +00:00
$platform->init(Service::TYPE_TASK);
2022-07-13 06:26:22 +00:00
2022-11-14 10:29:10 +00:00
$cli = $platform->getCli();
2022-11-16 15:28:15 +00:00
$cli
->error()
->inject('error')
2022-11-16 19:39:35 +00:00
->action(function (Throwable $error) {
2022-11-16 15:28:15 +00:00
Console::error($error->getMessage());
});
2024-10-08 07:54:40 +00:00
$cli->run();