From 95aaba43facc474907cbe520fdba5f3494e76cc3 Mon Sep 17 00:00:00 2001 From: Reto Brunner Date: Fri, 30 Dec 2022 17:20:53 +0100 Subject: [PATCH] cli: Implement storage migrate subcommand This introduces the ability to run the migration offline, while TL is not running as the migrations can take a long time. The migrate command is added as a `thelounge storage` subcommand. Reason being that it is expected that more subcommands will follow, say `thelounge storage clean` to remove partial data from the db. --- server/command-line/index.ts | 1 + server/command-line/storage.ts | 51 ++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 server/command-line/storage.ts diff --git a/server/command-line/index.ts b/server/command-line/index.ts index e164e63a..9127ad29 100644 --- a/server/command-line/index.ts +++ b/server/command-line/index.ts @@ -42,6 +42,7 @@ program.addCommand(require("./install").default); program.addCommand(require("./uninstall").default); program.addCommand(require("./upgrade").default); program.addCommand(require("./outdated").default); +program.addCommand(require("./storage").default); if (!Config.values.public) { require("./users").default.forEach((command: Command) => { diff --git a/server/command-line/storage.ts b/server/command-line/storage.ts new file mode 100644 index 00000000..6f1d5673 --- /dev/null +++ b/server/command-line/storage.ts @@ -0,0 +1,51 @@ +import log from "../log"; +import {Command} from "commander"; +import ClientManager from "../clientManager"; +import Utils from "./utils"; +import SqliteMessageStorage from "../plugins/messageStorage/sqlite"; + +const program = new Command("storage").description( + "various utilities related to the message storage" +); + +program + .command("migrate") + .argument("[user]", "migrate a specific user only, all if not provided") + .description("Migrate message storage where needed") + .on("--help", Utils.extraHelp) + .action(function (user) { + runMigrations(user).catch((err) => { + log.error(err.toString()); + process.exit(1); + }); + }); + +async function runMigrations(user: string) { + const manager = new ClientManager(); + const users = manager.getUsers(); + + if (user) { + if (!users.includes(user)) { + throw new Error(`invalid user ${user}`); + } + + return migrateUser(user); + } + + for (const name of users) { + await migrateUser(name); + // if any migration fails we blow up, + // chances are the rest won't complete either + } +} + +// runs sqlite migrations for a user, which must exist +async function migrateUser(user: string) { + log.info("handling user", user); + const sqlite = new SqliteMessageStorage(user); + await sqlite.enable(); // enable runs migrations + await sqlite.close(); + log.info("user", user, "migrated successfully"); +} + +export default program;