mirror of
https://github.com/openvk/openvk
synced 2025-07-04 06:49:50 +03:00
feat(install): Make upgrade script also work for eventdb
This commit is contained in:
parent
b5b4853891
commit
44a4959611
6 changed files with 215 additions and 118 deletions
|
@ -24,8 +24,9 @@ class FetchToncoinTransactions extends Command
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$ctx = DatabaseConnection::i()->getContext();
|
$ctx = DatabaseConnection::i()->getContext();
|
||||||
if (in_array("cryptotransactions", $ctx->getStructure()->getTables()))
|
if (in_array("cryptotransactions", $ctx->getStructure()->getTables())) {
|
||||||
$this->transactions = $ctx->table("cryptotransactions");
|
$this->transactions = $ctx->table("cryptotransactions");
|
||||||
|
}
|
||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,9 @@ class RebuildImagesCommand extends Command
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$ctx = DatabaseConnection::i()->getContext();
|
$ctx = DatabaseConnection::i()->getContext();
|
||||||
if (in_array("photos", $ctx->getStructure()->getTables()))
|
if (in_array("photos", $ctx->getStructure()->getTables())) {
|
||||||
$this->images = $ctx->table("photos");
|
$this->images = $ctx->table("photos");
|
||||||
|
}
|
||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,12 @@ use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
class UpgradeCommand extends Command {
|
class UpgradeCommand extends Command
|
||||||
|
{
|
||||||
protected static $defaultName = "upgrade";
|
protected static $defaultName = "upgrade";
|
||||||
|
|
||||||
private Connection $db;
|
private Connection $db;
|
||||||
|
private Connection $eventDb;
|
||||||
|
|
||||||
private array $chandlerTables = [
|
private array $chandlerTables = [
|
||||||
"CHANDLERACLPERMISSIONALIASES",
|
"CHANDLERACLPERMISSIONALIASES",
|
||||||
|
@ -26,12 +28,13 @@ class UpgradeCommand extends Command {
|
||||||
"CHANDLERACLRELATIONS",
|
"CHANDLERACLRELATIONS",
|
||||||
"CHANDLERGROUPS",
|
"CHANDLERGROUPS",
|
||||||
"CHANDLERTOKENS",
|
"CHANDLERTOKENS",
|
||||||
"CHANDLERUSERS"
|
"CHANDLERUSERS",
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->db = DatabaseConnection::i()->getConnection();
|
$this->db = DatabaseConnection::i()->getConnection();
|
||||||
|
$this->eventDb = eventdb()->getConnection();
|
||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
@ -40,78 +43,118 @@ class UpgradeCommand extends Command {
|
||||||
{
|
{
|
||||||
$this->setDescription("Upgrade OpenVK installation")
|
$this->setDescription("Upgrade OpenVK installation")
|
||||||
->setHelp("This command upgrades database schema after OpenVK was updated")
|
->setHelp("This command upgrades database schema after OpenVK was updated")
|
||||||
->addOption("quick", "Q", InputOption::VALUE_NEGATABLE,
|
->addOption(
|
||||||
"Don't display warning before migrating database", false)
|
"quick",
|
||||||
->addOption("repair", "R", InputOption::VALUE_NEGATABLE,
|
"Q",
|
||||||
"Attempt to repair database schema if tables are missing", false)
|
InputOption::VALUE_NEGATABLE,
|
||||||
->addOption("oneshot", "O", InputOption::VALUE_NONE,
|
"Don't display warning before migrating database",
|
||||||
"Only execute one operation")
|
false
|
||||||
->addArgument("chandler", InputArgument::OPTIONAL,
|
)
|
||||||
"Location of Chandler installation");
|
->addOption(
|
||||||
|
"repair",
|
||||||
|
"R",
|
||||||
|
InputOption::VALUE_NEGATABLE,
|
||||||
|
"Attempt to repair database schema if tables are missing",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
->addOption(
|
||||||
|
"oneshot",
|
||||||
|
"O",
|
||||||
|
InputOption::VALUE_NONE,
|
||||||
|
"Only execute one operation"
|
||||||
|
)
|
||||||
|
->addArgument(
|
||||||
|
"chandler",
|
||||||
|
InputArgument::OPTIONAL,
|
||||||
|
"Location of Chandler installation"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function checkDatabaseReadiness(bool &$chandlerOk, bool &$ovkOk, bool &$migrationsOk): void
|
protected function checkDatabaseReadiness(bool &$chandlerOk, bool &$ovkOk, bool &$eventOk, bool &$migrationsOk): void
|
||||||
{
|
{
|
||||||
$tables = $this->db->query("SHOW TABLES")->fetchAll();
|
$tables = $this->db->query("SHOW TABLES")->fetchAll();
|
||||||
$tables = array_map(fn ($x) => strtoupper($x->offsetGet(0)), $tables);
|
$tables = array_map(fn($x) => strtoupper($x->offsetGet(0)), $tables);
|
||||||
|
|
||||||
$missingTables = array_diff($this->chandlerTables, $tables);
|
$missingTables = array_diff($this->chandlerTables, $tables);
|
||||||
if (sizeof($missingTables) == 0)
|
if (sizeof($missingTables) == 0) {
|
||||||
$chandlerOk = true;
|
$chandlerOk = true;
|
||||||
else if (sizeof($missingTables) == sizeof($this->chandlerTables))
|
} elseif (sizeof($missingTables) == sizeof($this->chandlerTables)) {
|
||||||
$chandlerOk = null;
|
$chandlerOk = null;
|
||||||
else
|
} else {
|
||||||
$chandlerOk = false;
|
$chandlerOk = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($this->eventDb)) {
|
||||||
|
$eventOk = false;
|
||||||
|
} elseif (is_null($this->eventDb->query("SHOW TABLES LIKE \"notifications\"")->fetch())) {
|
||||||
|
$eventOk = null;
|
||||||
|
} else {
|
||||||
|
$eventOk = true;
|
||||||
|
}
|
||||||
|
|
||||||
$ovkOk = in_array("PROFILES", $tables);
|
$ovkOk = in_array("PROFILES", $tables);
|
||||||
$migrationsOk = in_array("OVK_UPGRADE_HISTORY", $tables);
|
$migrationsOk = in_array("OVK_UPGRADE_HISTORY", $tables);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function executeSqlScript(int $errCode, string $script, SymfonyStyle $io, bool $transaction = false): int
|
protected function executeSqlScript(
|
||||||
{
|
int $errCode,
|
||||||
$pdo = $this->db->getPdo();
|
string $script,
|
||||||
|
SymfonyStyle $io,
|
||||||
|
bool $transaction = false,
|
||||||
|
bool $eventDb = false
|
||||||
|
): int {
|
||||||
|
$pdo = ($eventDb ? $this->eventDb : $this->db)->getPdo();
|
||||||
|
|
||||||
$res = false;
|
$res = false;
|
||||||
try {
|
try {
|
||||||
if ($transaction)
|
if ($transaction) {
|
||||||
$res = $pdo->beginTransaction();
|
$res = $pdo->beginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
$res = $pdo->exec($script);
|
$res = $pdo->exec($script);
|
||||||
|
|
||||||
if ($transaction)
|
if ($transaction) {
|
||||||
$res = $pdo->commit();
|
$res = $pdo->commit();
|
||||||
} catch (\PDOException $e) {}
|
}
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
}
|
||||||
|
|
||||||
if ($res === false)
|
if ($res === false) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
$io->getErrorStyle()->error([
|
$io->getErrorStyle()->error([
|
||||||
"Failed to execute SQL statement:",
|
"Failed to execute SQL statement:",
|
||||||
implode("\t", $pdo->errorInfo())
|
implode("\t", $pdo->errorInfo()),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $errCode;
|
return $errCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getNextLevel(): int
|
protected function getNextLevel(bool $eventDb = false): int
|
||||||
{
|
{
|
||||||
$record = $this->db->query("SELECT level FROM ovk_upgrade_history ORDER BY level DESC LIMIT 1");
|
$db = $eventDb ? $this->eventDb : $this->db;
|
||||||
if (!$record->getRowCount())
|
$tbl = $eventDb ? "ovk_events_upgrade_history" : "ovk_upgrade_history";
|
||||||
|
$record = $db->query("SELECT level FROM $tbl ORDER BY level DESC LIMIT 1");
|
||||||
|
if (!$record->getRowCount()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return $record->fetchField() + 1;
|
return $record->fetchField() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getMigrationFiles(): array
|
protected function getMigrationFiles(bool $eventDb = false): array
|
||||||
{
|
{
|
||||||
$files = [];
|
$files = [];
|
||||||
$root = dirname(__DIR__ . "/../install/init-static-db.sql");
|
$root = dirname(__DIR__ . "/../install/init-static-db.sql");
|
||||||
|
$dir = $eventDb ? "sqls/eventdb" : "sqls";
|
||||||
|
|
||||||
foreach (glob("$root/sqls/*.sql") as $file)
|
foreach (glob("$root/$dir/*.sql") as $file) {
|
||||||
$files[(int) basename($file)] = basename($file);
|
$files[(int) basename($file)] = basename($file);
|
||||||
|
}
|
||||||
|
|
||||||
ksort($files);
|
ksort($files);
|
||||||
|
|
||||||
|
@ -125,8 +168,9 @@ class UpgradeCommand extends Command {
|
||||||
|
|
||||||
if (!file_exists($chandlerConfigLocation)) {
|
if (!file_exists($chandlerConfigLocation)) {
|
||||||
$err = ["Could not find chandler location. Perhaps your config is too unique?"];
|
$err = ["Could not find chandler location. Perhaps your config is too unique?"];
|
||||||
if (!$input->getOption("chandler"))
|
if (!$input->getOption("chandler")) {
|
||||||
$err[] = "Specify absolute path to your chandler installation using the --chandler option.";
|
$err[] = "Specify absolute path to your chandler installation using the --chandler option.";
|
||||||
|
}
|
||||||
|
|
||||||
$io->getErrorStyle()->error($err);
|
$io->getErrorStyle()->error($err);
|
||||||
|
|
||||||
|
@ -137,8 +181,9 @@ class UpgradeCommand extends Command {
|
||||||
$bar = new ProgressBar($io, sizeof($this->chandlerTables));
|
$bar = new ProgressBar($io, sizeof($this->chandlerTables));
|
||||||
$io->writeln("Dropping chandler tables...");
|
$io->writeln("Dropping chandler tables...");
|
||||||
|
|
||||||
foreach ($bar->iterate($this->chandlerTables) as $table)
|
foreach ($bar->iterate($this->chandlerTables) as $table) {
|
||||||
$this->db->query("DROP TABLE IF EXISTS $table;");
|
$this->db->query("DROP TABLE IF EXISTS $table;");
|
||||||
|
}
|
||||||
|
|
||||||
$io->newLine();
|
$io->newLine();
|
||||||
}
|
}
|
||||||
|
@ -155,21 +200,40 @@ class UpgradeCommand extends Command {
|
||||||
return $this->executeSqlScript(31, $installFile, $io);
|
return $this->executeSqlScript(31, $installFile, $io);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function initEventSchema(SymfonyStyle $io): int
|
||||||
|
{
|
||||||
|
$installFile = file_get_contents(__DIR__ . "/../install/init-event-db.sql");
|
||||||
|
|
||||||
|
return $this->executeSqlScript(31, $installFile, $io, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
protected function initUpgradeLog(SymfonyStyle $io): int
|
protected function initUpgradeLog(SymfonyStyle $io): int
|
||||||
{
|
{
|
||||||
$installFile = file_get_contents(__DIR__ . "/../install/init-migration-table.sql");
|
$installFile = file_get_contents(__DIR__ . "/../install/init-migration-table.sql");
|
||||||
|
$rc = $this->executeSqlScript(31, $installFile, $io);
|
||||||
|
if ($rc) {
|
||||||
|
var_dump($rc);
|
||||||
|
return $rc;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->executeSqlScript(31, $installFile, $io);
|
$installFile = file_get_contents(__DIR__ . "/../install/init-migration-table-event.sql");
|
||||||
|
|
||||||
|
return $this->executeSqlScript(32, $installFile, $io, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function runMigrations(SymfonyStyle $io, bool $oneshot): int
|
protected function runMigrations(SymfonyStyle $io, bool $eventDb, bool $oneshot): int
|
||||||
{
|
{
|
||||||
$nextLevel = $this->getNextLevel();
|
$dir = $eventDb ? "sqls/eventdb" : "sqls";
|
||||||
$migrations = array_filter($this->getMigrationFiles(), fn ($id) => $id >= $nextLevel, ARRAY_FILTER_USE_KEY);
|
$tbl = $eventDb ? "ovk_events_upgrade_history" : "ovk_upgrade_history";
|
||||||
|
$db = $eventDb ? $this->eventDb : $this->db;
|
||||||
|
$nextLevel = $this->getNextLevel($eventDb);
|
||||||
|
$migrations = array_filter(
|
||||||
|
$this->getMigrationFiles($eventDb),
|
||||||
|
fn($id) => $id >= $nextLevel,
|
||||||
|
ARRAY_FILTER_USE_KEY
|
||||||
|
);
|
||||||
|
|
||||||
if (!sizeof($migrations)) {
|
if (!sizeof($migrations)) {
|
||||||
$io->writeln("Database up to date. Nothing left to do.");
|
|
||||||
|
|
||||||
return 24;
|
return 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,8 +242,8 @@ class UpgradeCommand extends Command {
|
||||||
$bar->setFormat("very_verbose");
|
$bar->setFormat("very_verbose");
|
||||||
|
|
||||||
foreach ($bar->iterate($migrations) as $num => $migration) {
|
foreach ($bar->iterate($migrations) as $num => $migration) {
|
||||||
$script = file_get_contents(__DIR__ . "/../install/sqls/$migration");
|
$script = file_get_contents(__DIR__ . "/../install/$dir/$migration");
|
||||||
$res = $this->executeSqlScript(100 + $num, $script, $io, true);
|
$res = $this->executeSqlScript(100 + $num, $script, $io, true, $eventDb);
|
||||||
if ($res != 0) {
|
if ($res != 0) {
|
||||||
$io->getErrorStyle()->error("Error while executing migration №$num");
|
$io->getErrorStyle()->error("Error while executing migration №$num");
|
||||||
|
|
||||||
|
@ -187,12 +251,15 @@ class UpgradeCommand extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
$t = time();
|
$t = time();
|
||||||
$this->db->query("INSERT INTO ovk_upgrade_history VALUES ($num, $t, \"$uname\");");
|
$db->query("INSERT INTO $tbl VALUES ($num, $t, \"$uname\");");
|
||||||
|
|
||||||
if ($oneshot)
|
if ($oneshot) {
|
||||||
return 5;
|
return 5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$io->newLine();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,16 +277,17 @@ class UpgradeCommand extends Command {
|
||||||
|
|
||||||
$migrationsOk = false;
|
$migrationsOk = false;
|
||||||
$chandlerOk = false;
|
$chandlerOk = false;
|
||||||
|
$eventOk = false;
|
||||||
$ovkOk = false;
|
$ovkOk = false;
|
||||||
|
|
||||||
$this->checkDatabaseReadiness($chandlerOk, $ovkOk, $migrationsOk);
|
$this->checkDatabaseReadiness($chandlerOk, $ovkOk, $eventOk, $migrationsOk);
|
||||||
|
|
||||||
$res = -1;
|
$res = -1;
|
||||||
if ($chandlerOk === null) {
|
if ($chandlerOk === null) {
|
||||||
$io->writeln("Chandler schema not detected, attempting to install...");
|
$io->writeln("Chandler schema not detected, attempting to install...");
|
||||||
|
|
||||||
$res = $this->installChandler($input, $io);
|
$res = $this->installChandler($input, $io);
|
||||||
} else if ($chandlerOk === false) {
|
} elseif ($chandlerOk === false) {
|
||||||
if ($input->getOption("repair")) {
|
if ($input->getOption("repair")) {
|
||||||
$io->warning("Chandler schema detected but is broken, attempting to repair...");
|
$io->warning("Chandler schema detected but is broken, attempting to repair...");
|
||||||
|
|
||||||
|
@ -232,40 +300,65 @@ class UpgradeCommand extends Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($res > 0)
|
if ($res > 0) {
|
||||||
return $res;
|
return $res;
|
||||||
else if ($res == 0 && $oneShotMode)
|
} elseif ($res == 0 && $oneShotMode) {
|
||||||
return 5;
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$ovkOk) {
|
if (!$ovkOk) {
|
||||||
$io->writeln("Initializing OpenVK schema...");
|
$io->writeln("Initializing OpenVK schema...");
|
||||||
$res = $this->initSchema($io);
|
$res = $this->initSchema($io);
|
||||||
if ($res > 0)
|
if ($res > 0) {
|
||||||
return $res;
|
return $res;
|
||||||
else if ($oneShotMode)
|
} elseif ($oneShotMode) {
|
||||||
return 5;
|
return 5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$migrationsOk) {
|
if (!$migrationsOk) {
|
||||||
$io->writeln("Initializing upgrade log...");
|
$io->writeln("Initializing upgrade log...");
|
||||||
$res = $this->initUpgradeLog($io);
|
$res = $this->initUpgradeLog($io);
|
||||||
if ($res > 0)
|
if ($res > 0) {
|
||||||
return $res;
|
return $res;
|
||||||
else if ($oneShotMode)
|
} elseif ($oneShotMode) {
|
||||||
return 5;
|
return 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($eventOk !== false) {
|
||||||
|
if ($eventOk === null) {
|
||||||
|
$io->writeln("Initializing event database...");
|
||||||
|
$res = $this->initEventSchema($io);
|
||||||
|
if ($res > 0) {
|
||||||
|
return $res;
|
||||||
|
} elseif ($oneShotMode) {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$io->writeln("Upgrading event database...");
|
||||||
|
$res = $this->runMigrations($io, true, $oneShotMode);
|
||||||
|
if ($res == 24) {
|
||||||
|
$output->writeln("Event database already up to date.");
|
||||||
|
} elseif ($res > 0) {
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$io->writeln("Upgrading database...");
|
$io->writeln("Upgrading database...");
|
||||||
$res = $this->runMigrations($io, $oneShotMode);
|
$res = $this->runMigrations($io, false, $oneShotMode);
|
||||||
|
|
||||||
if (!$res) {
|
if (!$res) {
|
||||||
$io->success("Database has been upgraded!");
|
$io->success("Database has been upgraded!");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else if ($res != 24) {
|
} elseif ($res != 24) {
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$io->writeln("Database up to date. Nothing left to do.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -443,8 +443,9 @@ function downloadable_name(string $text): string
|
||||||
}
|
}
|
||||||
|
|
||||||
return (function () {
|
return (function () {
|
||||||
if (php_sapi_name() != "cli")
|
if (php_sapi_name() != "cli") {
|
||||||
_ovk_check_environment();
|
_ovk_check_environment();
|
||||||
|
}
|
||||||
|
|
||||||
require __DIR__ . "/vendor/autoload.php";
|
require __DIR__ . "/vendor/autoload.php";
|
||||||
|
|
||||||
|
|
5
install/init-migration-table-event.sql
Normal file
5
install/init-migration-table-event.sql
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
CREATE TABLE `ovk_events_upgrade_history` (
|
||||||
|
`level` smallint UNSIGNED NOT NULL,
|
||||||
|
`timestamp` bigint(20) UNSIGNED NOT NULL,
|
||||||
|
`operator` varchar(256) COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT "Maintenance Script"
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
|
|
@ -1,9 +1,5 @@
|
||||||
START TRANSACTION;
|
|
||||||
|
|
||||||
CREATE TABLE `ovk_upgrade_history` (
|
CREATE TABLE `ovk_upgrade_history` (
|
||||||
`level` smallint UNSIGNED NOT NULL,
|
`level` smallint UNSIGNED NOT NULL,
|
||||||
`timestamp` bigint(20) UNSIGNED NOT NULL,
|
`timestamp` bigint(20) UNSIGNED NOT NULL,
|
||||||
`operator` varchar(256) COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT "Maintenance Script"
|
`operator` varchar(256) COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT "Maintenance Script"
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
|
||||||
|
|
||||||
COMMIT;
|
|
Loading…
Reference in a new issue