vulpes
Version:
Job management framework
192 lines (176 loc) • 8.18 kB
JavaScript
;
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var uuid = require("uuid/v4");
var ms = require("ms");
var nested = require("nested-property");
var _require = require("./time.js"),
getTimestamp = _require.getTimestamp;
var _require2 = require("./cloning.js"),
cloneJob = _require2.cloneJob;
var _require3 = require("./symbols.js"),
ITEM_TYPE = _require3.ITEM_TYPE,
ITEM_TYPE_JOB = _require3.ITEM_TYPE_JOB,
JOB_PRIORITY_NORMAL = _require3.JOB_PRIORITY_NORMAL,
JOB_RESULT_TYPES_REXP = _require3.JOB_RESULT_TYPES_REXP,
JOB_STATUS_PENDING = _require3.JOB_STATUS_PENDING,
JOB_STATUS_REXP = _require3.JOB_STATUS_REXP;
/**
* New job data
* @typedef {Object} NewJob
* @property {String=} type - The type of job (custom, controlled by the consumer)
* @property {Priority=} priority - The priority of the job (defaults to normal priority)
* @property {Array.<String>=} parents - Parents of this job
* @property {String=} predicate - The predicate function that should evaluate to true
* before this job can run
* @property {Object=} data - Data for this job
* @property {Number=} timeLimit - Time limit in milliseconds (defaults to the default
* timelimit on the Service instance). Set to null to disable timeouts.
* @property {Number=} attemptsMax - The maximum number of soft failures that can occur
* before this job
* @property {Boolean=} archived - Determining if job will be excluded from queries or not
*/
var CONFIGURABLE_JOB_KEYS = ["data", "parents", "predicate", "priority", "result.data", "result.type", "timeLimit", "type"];
var DEFAULT_JOB_TYPE = "generic";
var JOB_VALIDATION = {
archived: [function (a) {
return typeof a === "boolean";
}],
data: [function (d) {
return (typeof d === "undefined" ? "undefined" : _typeof(d)) === "object" && d !== null;
}, function () {
return {};
}],
created: [function (c) {
return c > 0;
}, function () {
return Date.now();
}],
parents: [function (p) {
return Array.isArray(p);
}, function () {
return [];
}],
predicate: [function (p) {
return (typeof p === "undefined" ? "undefined" : _typeof(p)) === "object" && p !== null;
}, function () {
return generateEmptyJob().predicate;
}],
"predicate.attemptsMax": [function (a) {
return a === null || a > 0;
}, null],
"predicate.locked": [function (l) {
return typeof l === "boolean";
}, false],
"predicate.timeBetweenRetries": [function (t) {
return t === null || t >= 0;
}, function () {
return generateEmptyJob().predicate.timeBetweenRetries;
}],
priority: [function (p) {
return typeof p === "number" && !isNaN(p);
}, JOB_PRIORITY_NORMAL],
"result.data": [function (d) {
return (typeof d === "undefined" ? "undefined" : _typeof(d)) === "object" && d !== null;
}, function () {
return {};
}],
"result.type": [function (t) {
return t === null || JOB_RESULT_TYPES_REXP.test(t);
}, null],
timeLimit: [function (t) {
return t === null || t > 0;
}, null],
type: [function (t) {
return typeof t === "string";
}, DEFAULT_JOB_TYPE],
status: [function (s) {
return JOB_STATUS_REXP.test(s);
}, JOB_STATUS_PENDING]
};
function filterJobInitObject(info) {
var output = {};
CONFIGURABLE_JOB_KEYS.forEach(function (key) {
var value = nested.get(info, key);
if (typeof value !== "undefined") {
nested.set(output, key, value);
}
});
return output;
}
/**
* A job
* @typedef {Object} Job
* @property {String} id - The job's ID
* @property {String} type - The job type (consumer controlled)
* @property {Status} status - The current job state
* @property {Priority} priority - The job's priority
* @property {Number} created - The creation timestamp of the job
* @property {Array.<String>} parents - An array of IDs of the job's parents
* @property {Object} predicate - Predicate restraints for the job
* @property {Number} predicate.attemptsMax - Maximum attempts that can be undertaken
* on the job before it is failed
* @property {Number} predicate.timeBetweenRetries - Milliseconds between retries
* (minimum)
* @property {Object} data - The data for the job (incoming)
* @property {Object} result - Result information
* @property {ResultType|null} result.type - The type of result (null if not
* stopped at least once)
* @property {Object} result.data - Resulting data from the last execution
* (outgoing)
* @property {Object} times - Collection of notable timestamps for the job
* @property {Number|null} times.firstStarted - Timestamp for when the job was
* first started
* @property {Number|null} times.started - Timestamp for when the job was last
* started
* @property {Number|null} times.stopped - Timestamp for when the job was last
* stopped
* @property {Number|null} times.completed - Timestamp for when the job was
* completed successfully
* @property {Number|null} timeLimit - Time limitation for the job's
* execution. null means no limit.
* @property {Number} attempts - Number of attempts the job has had
* @property {Boolean} archived - True means the job will be archived and excluded from queries
*/
/**
* Generate an empty job
* @returns {Job} A new empty job
*/
function generateEmptyJob() {
var _ref;
var id = uuid();
return _ref = {}, _defineProperty(_ref, ITEM_TYPE, ITEM_TYPE_JOB), _defineProperty(_ref, "id", id), _defineProperty(_ref, "type", DEFAULT_JOB_TYPE), _defineProperty(_ref, "status", JOB_STATUS_PENDING), _defineProperty(_ref, "priority", JOB_PRIORITY_NORMAL), _defineProperty(_ref, "created", getTimestamp()), _defineProperty(_ref, "parents", []), _defineProperty(_ref, "predicate", {
attemptsMax: null,
locked: false,
timeBetweenRetries: ms("30s")
}), _defineProperty(_ref, "data", {}), _defineProperty(_ref, "result", {
data: {},
type: null
}), _defineProperty(_ref, "times", {
archived: null,
firstStarted: null,
started: null,
stopped: null,
completed: null
}), _defineProperty(_ref, "timeLimit", null), _defineProperty(_ref, "attempts", 0), _defineProperty(_ref, "archived", false), _ref;
}
function validateJobProperties(job) {
var output = cloneJob(job);
Object.keys(JOB_VALIDATION).forEach(function (key) {
var _JOB_VALIDATION$key = _slicedToArray(JOB_VALIDATION[key], 2),
test = _JOB_VALIDATION$key[0],
defaultValue = _JOB_VALIDATION$key[1];
var value = nested.get(output, key);
if (!test(value)) {
var newValue = typeof defaultValue === "function" ? defaultValue() : defaultValue;
nested.set(output, key, newValue);
}
});
return output;
}
module.exports = {
filterJobInitObject: filterJobInitObject,
generateEmptyJob: generateEmptyJob,
validateJobProperties: validateJobProperties
};