@clickup/pg-microsharding
Version:
Microshards support for PostgreSQL
122 lines • 5.57 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.actionFactor = actionFactor;
const difference_1 = __importDefault(require("lodash/difference"));
const flatten_1 = __importDefault(require("lodash/flatten"));
const groupBy_1 = __importDefault(require("lodash/groupBy"));
const round_1 = __importDefault(require("lodash/round"));
const sortBy_1 = __importDefault(require("lodash/sortBy"));
const prompts_1 = __importDefault(require("prompts"));
const table_1 = require("table");
const factor_1 = require("../api/factor");
const discoverShards_1 = require("../internal/discoverShards");
const getSchemaWeights_1 = require("../internal/getSchemaWeights");
const logging_1 = require("../internal/logging");
const names_1 = require("../internal/names");
const normalizeDsns_1 = require("../internal/normalizeDsns");
const promiseAllMap_1 = require("../internal/promiseAllMap");
const actionList_1 = require("./actionList");
/**
* Sets the weight factor for some shards.
*/
async function actionFactor(args) {
var _a, _b;
const dsns = await (0, normalizeDsns_1.normalizeDsns)(args["dsns"] || args["dsn"]);
if (dsns.length === 0) {
throw "Please provide --dsn or --dsns, DB DSN to adjust microshard(s) factor at";
}
let shardNos;
if ((_a = (args["shard"] || args["shards"])) === null || _a === void 0 ? void 0 : _a.match(/^(\d+(?:,\d+)*)$/)) {
shardNos = RegExp.$1.split(",").map(Number);
}
else if (args["shards"]) {
const matchingDsns = dsns.filter((dsn) => dsn.startsWith(args["shards"]) ||
(0, names_1.dsnShort)(dsn).startsWith(args["shards"]));
if (matchingDsns.length === 0) {
await (0, actionList_1.actionList)(args).catch(() => { });
throw "If you provide --shards, it must be in format: N,M,... or DSN-PREFIX";
}
shardNos = (await (0, discoverShards_1.discoverShards)({ dsns: matchingDsns })).map(({ shard }) => shard);
}
else {
await (0, actionList_1.actionList)(args).catch(() => { });
throw "Please provide --shard=N or --shards=N,M..., microshard numbers to set the factor for";
}
let factorSpec;
if ((_b = args["factor"]) === null || _b === void 0 ? void 0 : _b.match(/^([-+*])?(\d+(\.\d+)?)$/)) {
factorSpec = {
op: RegExp.$1,
num: parseFloat(RegExp.$2),
};
}
else {
await (0, actionList_1.actionList)(args).catch(() => { });
throw 'Please provide --factor=P|+P.Q|-P.Q|"*P.Q", factor to set for the microshards';
}
const allShards = await (0, discoverShards_1.discoverShards)({ dsns });
const matchingShards = (0, sortBy_1.default)(allShards.filter(({ shard }) => shardNos.includes(shard)), ({ shard }) => shard);
if (matchingShards.length === 0) {
throw "No microshards found to change the weight factors for.";
}
const missingShards = (0, difference_1.default)(shardNos, allShards.map(({ shard }) => shard));
if (missingShards.length > 0) {
throw `Microshards ${missingShards.join(", ")} not found in any of the DSNs`;
}
const plan = (0, flatten_1.default)(await (0, promiseAllMap_1.promiseAllMap)(Object.entries((0, groupBy_1.default)(matchingShards, "dsn")), async ([dsn, shards]) => {
const weights = await (0, getSchemaWeights_1.getSchemaWeights)({
dsn,
schemas: shards.map(({ schema }) => schema),
weightSql: undefined,
});
return shards.map(({ schema }) => {
const info = weights.get(schema);
const oldFactor = (info === null || info === void 0 ? void 0 : info.appliedFactor) || 1;
return {
dsn,
schema,
oldFactor,
newFactor: (0, round_1.default)(factorSpec.op === ""
? factorSpec.num
: factorSpec.op === "+"
? oldFactor + factorSpec.num
: factorSpec.op === "-"
? Math.max(oldFactor - factorSpec.num, 1)
: factorSpec.op === "*"
? oldFactor * factorSpec.num
: oldFactor, 3),
};
});
}));
(0, logging_1.print)((0, table_1.table)([
["DSN", "Microshard", "Current Factor", "New Factor"],
...plan.map(({ dsn, schema, oldFactor, newFactor }) => [
(0, names_1.dsnShort)(dsn),
schema,
oldFactor,
newFactor,
]),
], {
drawHorizontalLine: (i, rowCount) => i === 0 || i === 1 || i === rowCount,
}).trim());
const validResponse = "apply";
const response = await (0, prompts_1.default)({
type: "text",
name: "value",
message: `Type "${validResponse}" to apply the changes in weight factors:`,
validate: (value) => value !== validResponse
? `Enter "${validResponse}" to confirm, ^C to skip`
: true,
});
if (response.value !== validResponse) {
return false;
}
for (const { dsn, schema, newFactor } of plan) {
(0, logging_1.print)(`- ${(0, names_1.dsnShort)(dsn)}, ${schema}: setting factor=${newFactor}`);
await (0, factor_1.factor)({ dsn, schema, factor: newFactor });
}
return true;
}
//# sourceMappingURL=actionFactor.js.map