faastjs
Version:
Serverless batch computing made simple.
104 lines • 14.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkIteratorMessages = exports.expectMessage = exports.toArray = exports.sleep = exports.title = exports.noValidateConfigs = exports.configs = exports.record = exports.checkResourcesCleanedUp = exports.withClock = exports.stdev = exports.avg = exports.sum = exports.measureConcurrency = exports.keysOf = void 0;
const tslib_1 = require("tslib");
const lolex_1 = tslib_1.__importDefault(require("lolex"));
const util_1 = require("util");
const index_1 = require("../../index");
const serialize_1 = require("../../src/serialize");
const shared_1 = require("../../src/shared");
Object.defineProperty(exports, "keysOf", { enumerable: true, get: function () { return shared_1.keysOf; } });
const measureConcurrency = (timings) => timings
.map(t => t.start)
.map(t => timings.filter(({ start, end }) => start <= t && t < end).length)
.reduce((a, b) => Math.max(a, b));
exports.measureConcurrency = measureConcurrency;
const sum = (a) => a.reduce((total, n) => total + n, 0);
exports.sum = sum;
const avg = (a) => (0, exports.sum)(a) / a.length;
exports.avg = avg;
const stdev = (a) => {
const average = (0, exports.avg)(a);
return Math.sqrt((0, exports.avg)(a.map(v => (v - average) ** 2)));
};
exports.stdev = stdev;
async function withClock(fn) {
const clock = lolex_1.default.install({ shouldAdvanceTime: true, now: Date.now() });
try {
await fn(clock);
}
finally {
clock.uninstall();
}
}
exports.withClock = withClock;
function checkResourcesCleanedUp(t, resources) {
for (const key of (0, shared_1.keysOf)(resources)) {
t.is(resources[key], undefined);
if (resources[key] !== undefined) {
console.log(`Resource '${String(key)}' not cleaned up: %O`, resources[key]);
}
}
}
exports.checkResourcesCleanedUp = checkResourcesCleanedUp;
function record(fn) {
const func = Object.assign((...args) => {
const rv = fn(...args);
func.recordings.push({ args, rv });
index_1.log.info(`func.recordings: %O`, func.recordings);
return rv;
}, { recordings: [] });
return func;
}
exports.record = record;
exports.configs = [
// { mode: "https", childProcess: false, validateSerialization: true },
{ mode: "https", childProcess: true, validateSerialization: true },
// { mode: "queue", childProcess: false, validateSerialization: true },
{ mode: "queue", childProcess: true, validateSerialization: true }
];
exports.noValidateConfigs = exports.configs.map(c => ({
...c,
validateSerialization: false
}));
function title(provider, msg, options) {
const desc = options ? (0, util_1.inspect)(options, { breakLength: Infinity }) : "";
return [provider === "local" ? "" : "remote", provider, msg, desc]
.filter(x => x !== "")
.join(" ");
}
exports.title = title;
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
exports.sleep = sleep;
async function toArray(gen) {
const result = [];
for await (const elem of gen) {
result.push(elem);
}
return result;
}
exports.toArray = toArray;
function expectMessage(t, msg, kind, expected) {
t.is(msg.kind, kind);
if (msg.kind === kind) {
const [value] = (0, serialize_1.deserialize)(msg.value);
t.deepEqual(value, expected);
}
}
exports.expectMessage = expectMessage;
function checkIteratorMessages(t, rawMessages, arg) {
const messages = [];
t.is(rawMessages.length, arg.length + 1);
for (const msg of rawMessages) {
messages[msg.sequence] = msg;
}
let i = 0;
for (; i < arg.length; i++) {
expectMessage(t, messages[i], "iterator", { done: false, value: arg[i] });
}
expectMessage(t, messages[i], "iterator", { done: true });
}
exports.checkIteratorMessages = checkIteratorMessages;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvZml4dHVyZXMvdXRpbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQ0EsMERBQTBCO0FBQzFCLCtCQUErQjtBQUMvQix1Q0FBMkQ7QUFFM0QsbURBQWtEO0FBQ2xELDZDQUEwQztBQUVqQyx1RkFGQSxlQUFNLE9BRUE7QUFFUixNQUFNLGtCQUFrQixHQUFHLENBQUMsT0FBaUIsRUFBRSxFQUFFLENBQ3BELE9BQU87S0FDRixHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO0tBQ2pCLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO0tBQzFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFKN0IsUUFBQSxrQkFBa0Isc0JBSVc7QUFFbkMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFXLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQTVELFFBQUEsR0FBRyxPQUF5RDtBQUVsRSxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQVcsRUFBRSxFQUFFLENBQUMsSUFBQSxXQUFHLEVBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztBQUF6QyxRQUFBLEdBQUcsT0FBc0M7QUFFL0MsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFX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QUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDekMsS0FBSyxNQUFNLEdBQUcsSUFBSSxXQUFXLEVBQUU7UUFDM0IsUUFBUSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxHQUFHLENBQUM7S0FDaEM7SUFFRCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDVixPQUFPLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ3hCLGFBQWEsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7S0FDN0U7SUFDRCxhQUFhLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUM5RCxDQUFDO0FBaEJELHNEQWdCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEV4ZWN1dGlvbkNvbnRleHQgfSBmcm9tIFwiYXZhXCI7XG5pbXBvcnQgbG9sZXggZnJvbSBcImxvbGV4XCI7XG5pbXBvcnQgeyBpbnNwZWN0IH0gZnJvbSBcInV0aWxcIjtcbmltcG9ydCB7IENvbW1vbk9wdGlvbnMsIGxvZywgUHJvdmlkZXIgfSBmcm9tIFwiLi4vLi4vaW5kZXhcIjtcbmltcG9ydCB7IEl0ZXJhdG9yUmVzcG9uc2VNZXNzYWdlLCBNZXNzYWdlIH0gZnJvbSBcIi4uLy4uL3NyYy9wcm92aWRlclwiO1xuaW1wb3J0IHsgZGVzZXJpYWxpemUgfSBmcm9tIFwiLi4vLi4vc3JjL3NlcmlhbGl6ZVwiO1xuaW1wb3J0IHsga2V5c09mIH0gZnJvbSBcIi4uLy4uL3NyYy9zaGFyZWRcIjtcbmltcG9ydCB7IFRpbWluZyB9IGZyb20gXCIuL2Z1bmN0aW9uc1wiO1xuZXhwb3J0IHsga2V5c09mIH07XG5cbmV4cG9ydCBjb25zdCBtZWFzdXJlQ29uY3VycmVuY3kgPSAodGltaW5nczogVGltaW5nW10pID0+XG4gICAgdGltaW5nc1xuICAgICAgICAubWFwKHQgPT4gdC5zdGFydClcbiAgICAgICAgLm1hcCh0ID0+IHRpbWluZ3MuZmlsdGVyKCh7IHN0YXJ0LCBlbmQgfSkgPT4gc3RhcnQgPD0gdCAmJiB0IDwgZW5kKS5sZW5ndGgpXG4gICAgICAgIC5yZWR1Y2UoKGEsIGIpID0+IE1hdGgubWF4KGEsIGIpKTtcblxuZXhwb3J0IGNvbnN0IHN1bSA9IChhOiBudW1iZXJbXSkgPT4gYS5yZWR1Y2UoKHRvdGFsLCBuKSA9PiB0b3RhbCArIG4sIDApO1xuXG5leHBvcnQgY29uc3QgYXZnID0gKGE6IG51bWJlcltdKSA9PiBzdW0oYSkgLyBhLmxlbmd0aDtcblxuZXhwb3J0IGNvbnN0IHN0ZGV2ID0gKGE6IG51bWJlcltdKSA9PiB7XG4gICAgY29uc3QgYXZlcmFnZSA9IGF2ZyhhKTtcbiAgICByZXR1cm4gTWF0aC5zcXJ0KGF2ZyhhLm1hcCh2ID0+ICh2IC0gYXZlcmFnZSkgKiogMikpKTtcbn07XG5cbmV4cG9ydCB0eXBlIFZDbG9jayA9IGxvbGV4Lkluc3RhbGxlZENsb2NrPGxvbGV4LkNsb2NrPjtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdpdGhDbG9jayhmbjogKGNsb2NrOiBWQ2xvY2spID0+IFByb21pc2U8dm9pZD4pIHtcbiAgICBjb25zdCBjbG9jayA9IGxvbGV4Lmluc3RhbGwoeyBzaG91bGRBZHZhbmNlVGltZTogdHJ1ZSwgbm93OiBEYXRlLm5vdygpIH0pO1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGZuKGNsb2NrKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICBjbG9jay51bmluc3RhbGwoKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjaGVja1Jlc291cmNlc0NsZWFuZWRVcDxUIGV4dGVuZHMgb2JqZWN0PihcbiAgICB0OiBFeGVjdXRpb25Db250ZXh0LFxuICAgIHJlc291cmNlczogUGFydGlhbDxUPlxuKSB7XG4gICAgZm9yIChjb25zdCBrZXkgb2Yga2V5c09mKHJlc291cmNlcykpIHtcbiAgICAgICAgdC5pcyhyZXNvdXJjZXNba2V5XSwgdW5kZWZpbmVkKTtcbiAgICAgICAgaWYgKHJlc291cmNlc1trZXldICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBSZXNvdXJjZSAnJHtTdHJpbmcoa2V5KX0nIG5vdCBjbGVhbmVkIHVwOiAlT2AsIHJlc291cmNlc1trZXldKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWNvcmRlZENhbGw8QSBleHRlbmRzIGFueVtdLCBSPiB7XG4gICAgYXJnczogQTtcbiAgICBydjogUjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWNvcmRlZEZ1bmN0aW9uPEEgZXh0ZW5kcyBhbnlbXSwgUj4ge1xuICAgICguLi5hcmdzOiBBKTogUjtcbiAgICByZWNvcmRpbmdzOiBBcnJheTxSZWNvcmRlZENhbGw8QSwgUj4+O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVjb3JkPEEgZXh0ZW5kcyBhbnlbXSwgUj4oZm46ICguLi5hcmdzOiBBKSA9PiBSKSB7XG4gICAgY29uc3QgZnVuYzogUmVjb3JkZWRGdW5jdGlvbjxBLCBSPiA9IE9iamVjdC5hc3NpZ24oXG4gICAgICAgICguLi5hcmdzOiBBKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBydiA9IGZuKC4uLmFyZ3MpO1xuICAgICAgICAgICAgZnVuYy5yZWNvcmRpbmdzLnB1c2goeyBhcmdzLCBydiB9KTtcbiAgICAgICAgICAgIGxvZy5pbmZvKGBmdW5jLnJlY29yZGluZ3M6ICVPYCwgZnVuYy5yZWNvcmRpbmdzKTtcbiAgICAgICAgICAgIHJldHVybiBydjtcbiAgICAgICAgfSxcbiAgICAgICAgeyByZWNvcmRpbmdzOiBbXSB9XG4gICAgKTtcbiAgICByZXR1cm4gZnVuYztcbn1cblxuZXhwb3J0IGNvbnN0IGNvbmZpZ3M6IENvbW1vbk9wdGlvbnNbXSA9IFtcbiAgICAvLyB7IG1vZGU6IFwiaHR0cHNcIiwgY2hpbGRQcm9jZXNzOiBmYWxzZSwgdmFsaWRhdGVTZXJpYWxpemF0aW9uOiB0cnVlIH0sXG4gICAgeyBtb2RlOiBcImh0dHBzXCIsIGNoaWxkUHJvY2VzczogdHJ1ZSwgdmFsaWRhdGVTZXJpYWxpemF0aW9uOiB0cnVlIH0sXG4gICAgLy8geyBtb2RlOiBcInF1ZXVlXCIsIGNoaWxkUHJvY2VzczogZmFsc2UsIHZhbGlkYXRlU2VyaWFsaXphdGlvbjogdHJ1ZSB9LFxuICAgIHsgbW9kZTogXCJxdWV1ZVwiLCBjaGlsZFByb2Nlc3M6IHRydWUsIHZhbGlkYXRlU2VyaWFsaXphdGlvbjogdHJ1ZSB9XG5dO1xuXG5leHBvcnQgY29uc3Qgbm9WYWxpZGF0ZUNvbmZpZ3MgPSBjb25maWdzLm1hcChjID0+ICh7XG4gICAgLi4uYyxcbiAgICB2YWxpZGF0ZVNlcmlhbGl6YXRpb246IGZhbHNlXG59KSk7XG5cbmV4cG9ydCBmdW5jdGlvbiB0aXRsZShwcm92aWRlcjogUHJvdmlkZXIsIG1zZzogc3RyaW5nLCBvcHRpb25zPzogb2JqZWN0KSB7XG4gICAgY29uc3QgZGVzYyA9IG9wdGlvbnMgPyBpbnNwZWN0KG9wdGlvbnMsIHsgYnJlYWtMZW5ndGg6IEluZmluaXR5IH0pIDogXCJcIjtcbiAgICByZXR1cm4gW3Byb3ZpZGVyID09PSBcImxvY2FsXCIgPyBcIlwiIDogXCJyZW1vdGVcIiwgcHJvdmlkZXIsIG1zZywgZGVzY11cbiAgICAgICAgLmZpbHRlcih4ID0+IHggIT09IFwiXCIpXG4gICAgICAgIC5qb2luKFwiIFwiKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB0b0FycmF5PFQ+KGdlbjogQXN5bmNJdGVyYWJsZTxUPiB8IEl0ZXJhYmxlPFQ+KSB7XG4gICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgZm9yIGF3YWl0IChjb25zdCBlbGVtIG9mIGdlbikge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV4cGVjdE1lc3NhZ2U8VD4oXG4gICAgdDogRXhlY3V0aW9uQ29udGV4dCxcbiAgICBtc2c6IE1lc3NhZ2UsXG4gICAga2luZDogXCJwcm9taXNlXCIgfCBcIml0ZXJhdG9yXCIsXG4gICAgZXhwZWN0ZWQ6IFRcbikge1xuICAgIHQuaXMobXNnLmtpbmQsIGtpbmQpO1xuICAgIGlmIChtc2cua2luZCA9PT0ga2luZCkge1xuICAgICAgICBjb25zdCBbdmFsdWVdID0gZGVzZXJpYWxpemUobXNnLnZhbHVlKTtcbiAgICAgICAgdC5kZWVwRXF1YWwodmFsdWUsIGV4cGVjdGVkKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjaGVja0l0ZXJhdG9yTWVzc2FnZXMoXG4gICAgdDogRXhlY3V0aW9uQ29udGV4dCxcbiAgICByYXdNZXNzYWdlczogSXRlcmF0b3JSZXNwb25zZU1lc3NhZ2VbXSxcbiAgICBhcmc6IHN0cmluZ1tdXG4pIHtcbiAgICBjb25zdCBtZXNzYWdlcyA9IFtdO1xuICAgIHQuaXMocmF3TWVzc2FnZXMubGVuZ3RoLCBhcmcubGVuZ3RoICsgMSk7XG4gICAgZm9yIChjb25zdCBtc2cgb2YgcmF3TWVzc2FnZXMpIHtcbiAgICAgICAgbWVzc2FnZXNbbXNnLnNlcXVlbmNlXSA9IG1zZztcbiAgICB9XG5cbiAgICBsZXQgaSA9IDA7XG4gICAgZm9yICg7IGkgPCBhcmcubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZXhwZWN0TWVzc2FnZSh0LCBtZXNzYWdlc1tpXSwgXCJpdGVyYXRvclwiLCB7IGRvbmU6IGZhbHNlLCB2YWx1ZTogYXJnW2ldIH0pO1xuICAgIH1cbiAgICBleHBlY3RNZXNzYWdlKHQsIG1lc3NhZ2VzW2ldLCBcIml0ZXJhdG9yXCIsIHsgZG9uZTogdHJ1ZSB9KTtcbn1cbiJdfQ==