diff --git a/src/jio/core/JIO.js b/src/jio/core/JIO.js index f75c5a96aeaf783fc6913317c8e0b901e6eaf865..83348030eaad2d1806719c826e1d82dfb687e325 100644 --- a/src/jio/core/JIO.js +++ b/src/jio/core/JIO.js @@ -20,7 +20,7 @@ function JIO(storage_spec, options) { enableRestParamChecker(that, shared, options); enableJobMaker(that, shared, options); enableJobRetry(that, shared, options); - // enableJobChecker(that, shared, options); + enableJobChecker(that, shared, options); enableJobQueue(that, shared, options); enableJobRecovery(that, shared, options); enableJobTimeout(that, shared, options); diff --git a/src/jio/core/globals.js b/src/jio/core/globals.js index 344f8c20e9b5bb881908ba8fdb4e8e628f0474a0..9cc3337ca3fedd708ab1d80372bd49f1d87b642a 100644 --- a/src/jio/core/globals.js +++ b/src/jio/core/globals.js @@ -1,4 +1,5 @@ -/*jslint indent: 2, maxlen: 80, sloppy: true */ +/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */ +/*global uniqueJSONStringify */ var defaults = {}, constants = {}; @@ -330,6 +331,135 @@ constants.http_action = { constants.content_type_re = /^([a-z]+\/[a-zA-Z0-9\+\-\.]+)(?:\s*;\s*charset\s*=\s*([a-zA-Z0-9\-]+))?$/; +/** + * Function that does nothing + */ constants.emptyFunction = function () { return; }; + +defaults.job_rule_actions = {}; + +/** + * Adds some job rule actions + */ +(function () { + + /** + * Compare two jobs and test if they use the same storage description + * + * @param {Object} a The first job to compare + * @param {Object} b The second job to compare + * @return {Boolean} True if equal, else false + */ + function sameStorageDescription(a, b) { + return uniqueJSONStringify(a.storage_spec) === + uniqueJSONStringify(b.storage_spec); + } + + /** + * Guess if the method is a writer or a reader. + * + * @param {String} method The method name + * @return {String} "writer", "reader" or "unknown" + */ + function methodType(method) { + switch (method) { + case "post": + case "put": + case "putAttachment": + case "remove": + case "removeAttachment": + case "repair": + return 'writer'; + case "get": + case "getAttachment": + case "allDocs": + case "check": + return 'reader'; + default: + return 'unknown'; + } + } + + /** + * Compare two jobs and test if they are writers + * + * @param {Object} a The first job to compare + * @param {Object} b The second job to compare + * @return {Boolean} True if equal, else false + */ + function areWriters(a, b) { + return methodType(a.method) === 'writer' && + methodType(b.method) === 'writer'; + } + + /** + * Compare two jobs and test if they are readers + * + * @param {Object} a The first job to compare + * @param {Object} b The second job to compare + * @return {Boolean} True if equal, else false + */ + function areReaders(a, b) { + return methodType(a.method) === 'reader' && + methodType(b.method) === 'reader'; + } + + /** + * Compare two jobs and test if their methods are the same + * + * @param {Object} a The first job to compare + * @param {Object} b The second job to compare + * @return {Boolean} True if equal, else false + */ + function sameMethod(a, b) { + return a.method === b.method; + } + + /** + * Compare two jobs and test if their document ids are the same + * + * @param {Object} a The first job to compare + * @param {Object} b The second job to compare + * @return {Boolean} True if equal, else false + */ + function sameDocumentId(a, b) { + return a.kwargs._id === b.kwargs._id; + } + + /** + * Compare two jobs and test if their kwargs are equal + * + * @param {Object} a The first job to compare + * @param {Object} b The second job to compare + * @return {Boolean} True if equal, else false + */ + function sameParameters(a, b) { + return uniqueJSONStringify(a.kwargs) === + uniqueJSONStringify(b.kwargs); + } + + /** + * Compare two jobs and test if their options are equal + * + * @param {Object} a The first job to compare + * @param {Object} b The second job to compare + * @return {Boolean} True if equal, else false + */ + function sameOptions(a, b) { + return uniqueJSONStringify(a.options) === + uniqueJSONStringify(b.options); + } + + defaults.job_rule_actions = { + "sameStorageDescription": sameStorageDescription, + "areWriters": areWriters, + "areReaders": areReaders, + "sameMethod": sameMethod, + "sameDocumentId": sameDocumentId, + "sameParameters": sameParameters, + "sameOptions": sameOptions + }; + +}()); diff --git a/src/jio/features/jobChecker.js b/src/jio/features/jobChecker.js new file mode 100644 index 0000000000000000000000000000000000000000..f6e44d66f0923867ffa959fcee86522af340aeea --- /dev/null +++ b/src/jio/features/jobChecker.js @@ -0,0 +1,135 @@ +/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */ +/*global arrayInsert, indexOf, deepClone */ + +// creates +// - some defaults job rule actions + +function enableJobChecker(jio, shared, options) { + + // dependencies + // - shared.job_queue JobWorkspace + + // creates + // - shared.job_rules Array + + // uses 'job' events + + shared.job_check_method_names = [undefined, "ok", "wait", "update", "deny"]; + + function addJobRule(job_rule) { + var i, old_position, before_position, after_position; + // job_rule = { + // code_name: string + // conditions: [string, ...] + // action: 'wait', + // after: code_name + // before: code_name + // } + if (typeof job_rule !== 'object' || job_rule === null) { + // wrong job rule + return; + } + if (typeof job_rule.code_name !== 'string') { + // wrong code name + return; + } + if (!Array.isArray(job_rule.conditions)) { + // wrong conditions + return; + } + if (indexOf(job_rule.action, shared.job_check_method_names) === -1) { + // wrong action + return; + } + + if (typeof job_rule.after !== 'string') { + job_rule.after = ''; + } + if (typeof job_rule.before !== 'string') { + job_rule.before = ''; + } + + for (i = 0; i < shared.job_rules.length; i += 1) { + if (shared.job_rules[i].code_name === job_rule.after) { + after_position = i + 1; + } + if (shared.job_rules[i].code_name === job_rule.before) { + before_position = i; + } + if (shared.job_rules[i].code_name === job_rule.code_name) { + old_position = i; + } + } + + job_rule = { + "code_name": job_rule.code_name, + "conditions": job_rule.conditions, + "action": job_rule.action || "ok" + }; + + if (before_position === undefined) { + before_position = shared.job_rules.length; + } + if (after_position > before_position) { + before_position = undefined; + } + if (job_rule.action !== "ok" && before_position !== undefined) { + arrayInsert(shared.job_rules, before_position, job_rule); + } + if (old_position !== undefined) { + if (old_position >= before_position) { + old_position += 1; + } + shared.job_rules.splice(old_position, 1); + } + } + + if (options.job_management !== false) { + + shared.job_rules = [{ + "code_name": "readers update", + "conditions": [ + "sameStorageDescription", + "areReaders", + "sameMethod", + "sameParameters", + "sameOptions" + ], + "action": "update" + }, { + "code_name": "writers update", + "conditions": [ + "sameStorageDescription", + "areWriters", + "sameMethod", + "sameParameters" + ], + "action": "update" + }, { + "code_name": "writers wait", + "conditions": [ + "sameStorageDescription", + "areWriters", + "sameDocumentId" + ], + "action": "wait" + }]; + + var i; + if (Array.isArray(options.job_rules)) { + for (i = 0; i < options.job_rules.length; i += 1) { + addJobRule(deepClone(options.job_rules[i])); + } + } + + shared.on('job', function (param) { + // XXX + return; + }); + + } + + jio.jobRules = function () { + return deepClone(shared.job_rules); + }; +}