UNPKG

faastjs

Version:

Serverless batch computing made simple.

104 lines 14.8 kB
"use strict"; 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==