@noggin/elastic-noggin-sdk
Version:
Elastic Noggin SDK
172 lines (171 loc) • 7.71 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.calcQueryTimeouts = exports.execute = exports.execute1dWithResponseHeaders = exports.execute1d = void 0;
const EnoFactory_1 = require("./EnoFactory");
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const send_1 = require("./send");
const error_1 = require("./error");
const locale_1 = require("./locale");
const lodash_1 = require("lodash");
function execute1d(queryTip, enSrvOptions, options = {
branch: "branch/master",
lang: "en-us",
vars: {},
extraFilters: [],
extraAttributes: [],
dimensionOptions: [{ label: "Tip", formula: "TIP()" }],
includeFallbackLang: true
}, timeoutMs = 10000) {
return execute(queryTip, enSrvOptions, options, timeoutMs).pipe((0, operators_1.map)((response) => {
const keys = response.dimensions[0].values;
return response.results.map((result, i) => {
return result[keys[i]];
});
}));
}
exports.execute1d = execute1d;
function execute1dWithResponseHeaders(queryTip, enSrvOptions, options = {
branch: "branch/master",
lang: "en-us",
vars: {},
extraFilters: [],
extraAttributes: [],
dimensionOptions: [{ label: "Tip", formula: "TIP()" }],
includeFallbackLang: true,
responseHeadersToInclude: []
}, timeoutMs = 10000) {
return execute(queryTip, enSrvOptions, options, timeoutMs).pipe((0, operators_1.map)((response) => {
const keys = response.dimensions[0].values;
const results = response.results.map((result, i) => {
return result[keys[i]];
});
return response.responseHeaders
? { results, responseHeaders: response.responseHeaders }
: results;
}));
}
exports.execute1dWithResponseHeaders = execute1dWithResponseHeaders;
function execute(queryTip, enSrvOptions, options = {
branch: "branch/master",
lang: "en-us",
vars: {},
extraFilters: [],
dimensionOptions: [{ label: "Tip", formula: "TIP()" }],
includeFallbackLang: true,
responseHeadersToInclude: []
}, timeoutMs = 10000) {
const setNow = (now) => (0, lodash_1.set)(options, ["vars", "---NOW---"], [now]);
const timezone$ = (0, lodash_1.has)(options, ["vars", "---NOW---"])
? (0, rxjs_1.of)(null)
: (0, locale_1.nowVar)(enSrvOptions).pipe((0, operators_1.tap)(setNow));
const langs$ = (0, locale_1.getLangs)(enSrvOptions, (0, lodash_1.get)(options, "lang"), (0, lodash_1.get)(options, "includeFallbackLang", true));
const send$ = (langs) => {
const { queryTimeoutMs, observableTimeoutMs } = calcQueryTimeouts(timeoutMs);
const enoFactory = new EnoFactory_1.EnoFactory("op/query", "security/policy/op");
enoFactory.setField("op/query/tip", [queryTip]);
enoFactory.setField("op/query/branch", [(0, lodash_1.get)(options, 'branch', 'branch/master')]);
enoFactory.setField("op/query/lang", langs);
enoFactory.setField("op/query/timeout", [queryTimeoutMs.toString()]);
enoFactory.setField("op/query/query", [
JSON.stringify({
attributes: options.extraAttributes,
filters: options.extraFilters,
vars: options.vars || {},
dimensions: options.dimensionOptions || [],
lastPersist: options.lastPersist,
}),
]);
return (0, send_1.send)([enoFactory.makeEno()], enSrvOptions, options).pipe((0, operators_1.tap)(error_1.checkBatchForError), (0, operators_1.map)((batch) => parseResponse(batch, options === null || options === void 0 ? void 0 : options.responseHeadersToInclude)), (0, operators_1.timeout)(observableTimeoutMs));
};
return (0, rxjs_1.forkJoin)({ tz: timezone$, langs: langs$ }).pipe((0, operators_1.switchMap)(({ langs }) => send$(langs)));
}
exports.execute = execute;
function calcQueryTimeouts(timeoutMs) {
const timeoutBufferMs = 2000;
const minimumQueryTimeoutMs = 1000;
const maximumQueryTimeoutMs = 28000;
const minimumObservableTimeoutMs = 1500;
const queryTimeoutMs = Math.min(maximumQueryTimeoutMs, Math.max(minimumQueryTimeoutMs, timeoutMs - timeoutBufferMs));
const observableTimeoutMs = Math.max(minimumObservableTimeoutMs, timeoutMs);
return { queryTimeoutMs, observableTimeoutMs };
}
exports.calcQueryTimeouts = calcQueryTimeouts;
function parseResponse(sendBatch, responseHeaders) {
let packedResults = undefined;
const queryResponse = {
attributes: [],
dimensions: [],
execTime: undefined,
results: [],
};
let runtimeDims = [];
let runtimeAttrs = [];
sendBatch.forEach((eno) => {
switch (eno.getType()) {
case "response/query":
queryResponse.execTime = eno.getFieldNumberValue("response/query/exec-time");
runtimeAttrs = eno
.getFieldValues("response/query/runtime-attributes")
.map((attrJson) => JSON.parse(attrJson));
runtimeDims = eno
.getFieldValues("response/query/runtime-dimensions")
.map((dim) => JSON.parse(dim))
.map((dim) => ({ label: dim.label, values: dim.value }));
packedResults = eno.getFieldValues("response/query/result");
break;
case "response/query/dimension":
queryResponse.dimensions.push({
tip: eno.tip,
label: eno.getFieldStringValue("response/query/dimension/label"),
values: eno.getFieldValues("response/query/dimension/value"),
});
break;
case "query/attribute":
queryResponse.attributes.push({
tip: eno.tip,
label: eno.getFieldStringValue("query/attribute/label"),
formula: eno.getFieldStringValue("query/attribute/formula"),
});
break;
}
});
if (packedResults === undefined) {
throw new Error("No query response");
}
runtimeAttrs.forEach((runtimeAttr) => queryResponse.attributes.push(runtimeAttr));
runtimeDims.forEach((runtimeDim) => queryResponse.dimensions.push(runtimeDim));
if (queryResponse.dimensions.length === 0) {
throw new Error("No dimension in response");
}
queryResponse.results = unpackQueryResults(packedResults, queryResponse.dimensions, queryResponse.attributes);
return Object.assign(Object.assign({}, queryResponse), (responseHeaders ? { responseHeaders } : {}));
}
function unpackQueryResults(flatResult, dims, attrs, result = [], depth = 0) {
if (depth === dims.length - 1) {
let i = 0;
dims[dims.length - 1].values.forEach((lastDimValue) => {
const leafResult = {};
leafResult[lastDimValue] = {};
if (flatResult[i] === "{#}") {
i += attrs.length;
return;
}
for (const attr of attrs) {
leafResult[lastDimValue][attr.label] = flatResult[i++];
}
result.push(leafResult);
});
return result;
}
dims[depth].values.forEach((dimValue, i) => {
const subResult = [];
const subResultSize = flatResult.length / dims[depth].values.length;
const subResultStart = i * subResultSize;
const subResultEnd = subResultStart + subResultSize;
result[i] = {};
result[i][dimValue] = subResult;
unpackQueryResults(flatResult.slice(subResultStart, subResultEnd), dims, attrs, subResult, depth + 1);
});
return result;
}