Skip to content

Jayrule - Looping Asynchronous Rules

Applies to JayRule v20190819 (Guarded Giraffe) and later.

Occasionally we will want to run an asynchronous process on an unfixed number of items, such that we need to know the result of those operations before proceeding to the next rule, or in fact processing the next item in the same rule. Eg, we have fetched a number of sibling documents, and need to update each one, before moving onto our next process.

A special extended syntax for a rule has been formulated and implemented for doing this.

Syntax

rule-name : {

  ruleCondition : rule-condition-function | boolean,

  or

  fieldChanged : boolean,

  preLoop : preLoop-function

  arrayToProcess : arrayToProcess-function

  ruleItemProcess : ruleItemProcess-function

  ruleAction : rule-action-function

},

rule-name

Name of the rule. Same as for usual rules.

ruleCondition function / boolean

A function that returns true (or non-empty/non-zero) if the rule is to proceed.

This function must be of the format

function(ntf) {...}

Note: this function must not contain asynchronous processes.

Eg

ruleCondition : function(ntf) {
    return (ntf.context.fieldChanged === 'checkVenomous');
},

ruleCondition can also be assigned simply true (or false) for rules that must always (never) run.

Eg

ruleCondition : true,

fieldChanged

In the case of OnFieldChange rulesets only, we can specify just the name of the field changed. This replaces ruleCondition.

Eg

fieldChanged : 'customerName',

preLoop function

This occurs once the rule has been determined to run, according to the ruleCondition, and before any array item is processed.

Syntax

preLoop : function(ntf) {
    ...
}

arrayToProcess function

This function returns the array of objects/variables to be processed.

Syntax

arrayToProcess : function(ntf) {
    ...
}

If the function returns null, or an empty array, the rule will not run. No error is raised. You will see an indicator of null or empty array in the logging.

ruleItemProcess function

This function performs the process on each array item.

Syntax

ruleItemProcess : function(ntf, item, index, callback) {
    ...
}

This function requires that callback is called at the end of any processing, so the ruleset knows to proceed to the next array item.

ruleAction function

This function runs after all items have been processed. In general, it's used for any final tasks for the rule as a whole.

Unlike usual rules, this one must not use a callback in its arguments.

Syntax

ruleAction : function(ntf) {
    ...
}

Example

ruleCastChanges : {
    ruleCondition : function(ntf) { 
        var doChanges = !ntf.isClientEvent && ntf.document.status === 'Ready';
        return doChanges;
    },

    arrayToProcess: function(ntf) {
        return ntf.siblingDocIds;
    },

    preLoop : function(ntf) {
        ntf.castChangeSuccessCount = 0;
        ntf.castChangeFailCount = 0;
    },

    ruleItemProcess : function(ntf, documentId, index, callback) {
        var ft3 = ntf.scope;
        var change = {
            readyDate : ft3.moment().toDate();
        };

        ntf.logger.info('Updating ' + documentId + ' ...');
        ft3.updateDocument(documentId, change, ntf.userId, function(err, doc) {
            if (err) {
                ntf.logger.error('Error on update: ' + err.message);
                ntf.castChangeSuccessCount++;
            }
            else {
                ntf.logger.info('Document updated ok');
                ntf.castChangeFailCount++;
            }
            callback();
        });
    },

    ruleAction : function(ntf) { 
        ntf.logger.info('All sibling documents processed.');
        ntf.logger.info('# Successfully updated: ' + ntf.castChangeSuccessCount);
        ntf.logger.info('# Failed to update: ' + ntf.castChangeFailCount);
    }
},