indexbackup
Version:
Manticore Search physical backup utility
119 lines (116 loc) • 4.69 kB
JavaScript
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"));
})();