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