UNPKG

indexbackup

Version:

Manticore Search physical backup utility

148 lines (141 loc) 6.4 kB
#!/usr/bin/env node 'use strict'; var fs = require('fs'); var path = require('path'); var margv = require('margv'); var mariadb = require('mariadb'); var process$1 = require('process'); var archiver = require('archiver'); var chalk = require('chalk'); var stream = require('stream'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n["default"] = e; return Object.freeze(n); } var fs__namespace = /*#__PURE__*/_interopNamespace(fs); var path__namespace = /*#__PURE__*/_interopNamespace(path); var margv__default = /*#__PURE__*/_interopDefaultLegacy(margv); var mariadb__default = /*#__PURE__*/_interopDefaultLegacy(mariadb); var archiver__default = /*#__PURE__*/_interopDefaultLegacy(archiver); var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk); (async () => { const argv = margv__default["default"](); const showVersion = argv.v || argv.version; if (showVersion) { process$1.stdout.write("indexdump: 0.1.3\n"); process.exit(0); } const showHelp = !!argv.help; if (showHelp) { const TAB3 = " "; const TAB4 = " "; const TAB5 = " "; process$1.stdout.write(chalk__default["default"].green("List of settings\n")); process$1.stdout.write(chalk__default["default"].bold("-h/--host") + TAB4 + "host (default: 127.0.0.1)\n"); process$1.stdout.write(chalk__default["default"].bold("-P/--port") + TAB4 + "port (default: 9306)\n"); process$1.stdout.write(chalk__default["default"].bold("--dry-run") + TAB4 + "run in dry mode\n"); process$1.stdout.write(chalk__default["default"].bold("--index test1\n--index test2\n--index=test1,test2") + " indexes list for dump\n"); process$1.stdout.write(chalk__default["default"].bold("--all") + TAB5 + "backup of all indexes + manticore.json if the utility can find it\n"); process$1.stdout.write(chalk__default["default"].bold("--type=rt") + TAB4 + "only RT index types. Possible values local,distributed,rt,percolate,template\n"); process$1.stdout.write(chalk__default["default"].bold("--path") + TAB5 + "path from which the index will be restored (default: current)\n"); process$1.stdout.write(chalk__default["default"].bold("--data-dir") + TAB4 + "allow to set manticore data path\n"); process$1.stdout.write(chalk__default["default"].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 && process$1.stdout.write(chalk__default["default"].yellow("\n----- Start dry run -----\n")); const devNull = new stream.Writable({ write(chunk, encoding, callback) { setImmediate(callback); } }); const conn = await mariadb__default["default"].createConnection({ host, port }); const arch = archiver__default["default"]("tar", { gzip: true }); !dryRun && arch.pipe(process$1.stdout); dryRun && arch.pipe(devNull); let lastFile = ""; const promisifyStream = (file, name) => { dryRun && process$1.stdout.write(`${file}`); return new Promise((resolve) => { const entryListener = () => { arch.off("entry", entryListener); arch.off("error", errorListener); dryRun && process$1.stdout.write(chalk__default["default"].green(" done\n")); resolve(true); }; const errorListener = () => { arch.off("entry", entryListener); arch.off("error", errorListener); dryRun && process$1.stdout.write(chalk__default["default"].red(" not accessible\n")); resolve(true); }; arch.append(fs__namespace.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__namespace.join(index2, path__namespace.basename(file))); } } catch (e) { dryRun && process$1.stdout.write(chalk__default["default"].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 && process$1.stdout.write(chalk__default["default"].green(`${current} `)); await backup(current); } if (isAll || addConfig) { const base = dataDir || path__namespace.dirname(lastFile); if (base) { const manticoreJson = path__namespace.join(base, "..", "manticore.json"); try { dryRun && process$1.stdout.write(chalk__default["default"].green(`manticore.json `)); await promisifyStream(manticoreJson, path__namespace.basename(manticoreJson)); } catch (e) { } } } await arch.finalize(); await conn.end(); dryRun && process$1.stdout.write(chalk__default["default"].yellow("----- End dry run -----\n\n")); })();