UNPKG

indexbackup

Version:

Manticore Search physical backup utility

119 lines (116 loc) 4.69 kB
#!/usr/bin/env node import * as fs from 'fs'; import * as path from 'path'; import margv from 'margv'; import mariadb from 'mariadb'; import { stdout } from 'process'; import archiver from 'archiver'; import chalk from 'chalk'; import { Writable } from 'stream'; (async () => { const argv = margv(); const showVersion = argv.v || argv.version; if (showVersion) { stdout.write("indexdump: 0.1.3\n"); process.exit(0); } const showHelp = !!argv.help; if (showHelp) { const TAB3 = " "; const TAB4 = " "; const TAB5 = " "; stdout.write(chalk.green("List of settings\n")); stdout.write(chalk.bold("-h/--host") + TAB4 + "host (default: 127.0.0.1)\n"); stdout.write(chalk.bold("-P/--port") + TAB4 + "port (default: 9306)\n"); stdout.write(chalk.bold("--dry-run") + TAB4 + "run in dry mode\n"); stdout.write(chalk.bold("--index test1\n--index test2\n--index=test1,test2") + " indexes list for dump\n"); stdout.write(chalk.bold("--all") + TAB5 + "backup of all indexes + manticore.json if the utility can find it\n"); stdout.write(chalk.bold("--type=rt") + TAB4 + "only RT index types. Possible values local,distributed,rt,percolate,template\n"); stdout.write(chalk.bold("--path") + TAB5 + "path from which the index will be restored (default: current)\n"); stdout.write(chalk.bold("--data-dir") + TAB4 + "allow to set manticore data path\n"); stdout.write(chalk.bold("--add-config") + TAB3 + "add manticore.json to dump\n"); process.exit(0); } if (argv.$.length < 3) { console.error("Error parse arguments. Use: indexbackup index > name.tar.gz"); process.exit(1); } const host = (argv.$.find((v) => v.indexOf("-h") === 0) || "").replace("-h", "") || argv["h"] || argv["host"] || "127.0.01"; const port = (argv.$.find((v) => v.indexOf("-P") === 0) || "").replace("-P", "") || argv["P"] || argv["port"] || 9306; const index = argv.$.pop(); let indexes = argv["index"] ? Array.isArray(argv["index"]) ? argv["index"] : argv["index"].split(",").map((v) => v.trim()) : [index]; const isAll = !!argv["all"]; const types = argv["type"] ? Array.isArray(argv["type"]) ? argv["type"] : argv["type"].split(",").map((v) => v.trim()) : argv["type"]; const dryRun = !!argv["dry-run"]; const dataDir = argv["data-dir"] || ""; const addConfig = !!argv["add-config"]; dryRun && stdout.write(chalk.yellow("\n----- Start dry run -----\n")); const devNull = new Writable({ write(chunk, encoding, callback) { setImmediate(callback); } }); const conn = await mariadb.createConnection({ host, port }); const arch = archiver("tar", { gzip: true }); !dryRun && arch.pipe(stdout); dryRun && arch.pipe(devNull); let lastFile = ""; const promisifyStream = (file, name) => { dryRun && stdout.write(`${file}`); return new Promise((resolve) => { const entryListener = () => { arch.off("entry", entryListener); arch.off("error", errorListener); dryRun && stdout.write(chalk.green(" done\n")); resolve(true); }; const errorListener = () => { arch.off("entry", entryListener); arch.off("error", errorListener); dryRun && stdout.write(chalk.red(" not accessible\n")); resolve(true); }; arch.append(fs.createReadStream(file), { name }).on("entry", entryListener).on("error", errorListener); }); }; const backup = async (index2) => { try { const files = (await conn.query(`FREEZE ${index2}`)).map((row) => row["file"]); for (const file of files) { lastFile = file; await promisifyStream(file, path.join(index2, path.basename(file))); } } catch (e) { dryRun && stdout.write(chalk.red(e?.message || "Unknown error\n")); } finally { await conn.query(`UNFREEZE ${index2}`); } }; if (isAll) { let indexesRows = await conn.query(`SHOW TABLES;`); if (types?.length) { indexesRows = indexesRows.filter((index2) => types.includes(index2.Type)); } indexes = indexesRows.map((row) => row["Index"]); } for (const current of indexes) { dryRun && stdout.write(chalk.green(`${current} `)); await backup(current); } if (isAll || addConfig) { const base = dataDir || path.dirname(lastFile); if (base) { const manticoreJson = path.join(base, "..", "manticore.json"); try { dryRun && stdout.write(chalk.green(`manticore.json `)); await promisifyStream(manticoreJson, path.basename(manticoreJson)); } catch (e) { } } } await arch.finalize(); await conn.end(); dryRun && stdout.write(chalk.yellow("----- End dry run -----\n\n")); })();