Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async and fixed priority and on switch #1

Merged
merged 2 commits into from
May 28, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ A Rules consist of
"priority": 3,
"on":1,
"condition":
function(fact) {
return fact && (fact.transactionTotal < 500);
function(fact,cb) {
cb(fact && (fact.transactionTotal < 500));
},
"consequence":
function() {
function(cb) {
console.log("Rule 1 matched for "+this.name+": blocks transactions below value 500. Rejecting payment.");
this.result = false;
this.process = true;
cb();
}
}

Expand Down Expand Up @@ -78,14 +79,15 @@ var rules = [{
"priority": 3,
"on":1,
"condition":
function(fact) {
return fact && (fact.transactionTotal < 500);
function(fact,cb) {
cb(fact && (fact.transactionTotal < 500));
},
"consequence":
function() {
function(cb) {
console.log("Rule 1 matched for "+this.name+": blocks transactions below value 500. Rejecting payment.");
this.result = false;
this.process = true;
cb();
}
}];

Expand Down
29 changes: 19 additions & 10 deletions lib/node-rules.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
var _ = require('underscore'),
async = require("async");

exports.version = '0.0.1';
exports.version = '0.0.2';

function RuleEngine(rules) {

Expand All @@ -16,7 +16,13 @@ RuleEngine.prototype.execute = function (fact,callback) {
var session = _.clone(fact)
, last_session = _.clone(fact)
, goal = false;
var _rules = this.rules;
var _rules = [];
for(var i = 0; i < this.rules.length; i++) {
if(this.rules[i].on)
_rules[this.rules[i].priority] = this.rules[i];
}
_rules = _.compact(_rules);

session['process'] = false;
session['result'] = true;

Expand All @@ -36,9 +42,11 @@ RuleEngine.prototype.execute = function (fact,callback) {

function(cnd,callback) {

outcome = outcome && cnd.call({}, session);
cnd.call({}, session,function(out){
outcome = outcome && out;
callback();
});

callback();

},

Expand All @@ -50,12 +58,13 @@ RuleEngine.prototype.execute = function (fact,callback) {

function(csq,callback) {

csq.apply(session, []);

if (!_.isEqual(last_session,session)) {
changes = true;
last_session = _.clone(session);
}
csq.apply(session, [function(){
if (!_.isEqual(last_session,session)) {
changes = true;
last_session = _.clone(session);
}
callback();
}]);

},

Expand Down
40 changes: 0 additions & 40 deletions npm-debug.log

This file was deleted.

10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "node-rules",
"version": "0.1.0",
"version": "1.1.0",
"description": "Business Rules Engine for JavaScript",
"keywords": [
"bre",
Expand All @@ -11,7 +11,13 @@
"name": "Mithun Satheesh",
"email": "[email protected]"
},
"contributors": [],
"contributors": [
{
"name": "Abdul Munim Kazia",
"email" : "[email protected]",
"url" : "http://munimkazia.com"
}
],
"dependencies": {
"underscore": ">= 1.1.6",
"async":">=0.2.5"
Expand Down
63 changes: 36 additions & 27 deletions test/rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ var rules = [
"priority": 3,
"on":1,
"condition":
function(fact) {
return fact && (fact.transactionTotal < 500);
function(fact,cb) {
return cb(fact && (fact.transactionTotal < 500));
},
"consequence":
function() {
function(cb) {
console.log("Rule 1 matched for "+this.name+": blocks transactions below value 500. Rejecting payment.");
this.result = false;
this.process = true;
cb();
}
},
/**** Rule 2 ****/
Expand All @@ -27,14 +28,15 @@ var rules = [
"priority":2,
"on":1,
"condition":
function(fact) {
return fact && fact.userCredibility && (fact.userCredibility > 5);
function(fact,cb) {
return cb(fact && fact.userCredibility && (fact.userCredibility > 5));
},
"consequence":
function() {
function(cb) {
console.log("Rule 2 matched for "+this.name+": if the users credibility value is more, then avoid checking further. Accepting payment. ");
this.result = true;
this.process = true;
cb();
}
},
/**** Rule 3 ****/
Expand All @@ -44,14 +46,15 @@ var rules = [
"priority": 4,
"on":1,
"condition":
function(fact) {
return fact && (fact.cardType == "Credit Card") && (fact.cardIssuer == "American Express") && (fact.transactionTotal > 1000);
function(fact,cb) {
return cb(fact && (fact.cardType == "Credit Card") && (fact.cardIssuer == "American Express") && (fact.transactionTotal > 1000));
},
"consequence":
function() {
function(cb) {
console.log("Rule 3 matched for "+this.name+": filter American Express credit cards for payment above 10000. Rejecting payment.");
this.result = false;
this.process = true;
cb();
}
},
/**** Rule 4 ****/
Expand All @@ -61,14 +64,15 @@ var rules = [
"priority":8,
"on":1,
"condition":
function(fact) {
return fact && (fact.cardType == "Cash Card");
function(fact,cb) {
return cb(fact && (fact.cardType == "Cash Card"));
},
"consequence":
function() {
function(cb) {
console.log("Rule 4 matched for "+this.name+": reject the payment if the payment type belong to cash card. Rejecting payment.");
this.result = false;
this.process = true;
cb();
}
},
/**** Rule 5 ****/
Expand All @@ -78,14 +82,15 @@ var rules = [
"priority":6,
"on":1,
"condition":
function(fact) {
return fact && fact.customerType && (fact.transactionTotal > 10000) && (fact.customerType == "guest");
function(fact,cb) {
return cb(fact && fact.customerType && (fact.transactionTotal > 10000) && (fact.customerType == "guest"));
},
"consequence":
function() {
function(cb) {
console.log("Rule 5 matched for "+this.name+": reject the payment if the payment above 10000 and customer type is guest. Rejecting payment.");
this.result = false;
this.process = true;
cb();
}
},
/**** Rule 6 ****/
Expand All @@ -95,13 +100,14 @@ var rules = [
"priority":7,
"on":1,
"condition":
function(fact) {
return fact && !fact.userLoggedIn;
function(fact,cb) {
return cb(fact && !fact.userLoggedIn);
},
"consequence":
function() {
function(cb) {
console.log("Rule 6 matched for "+this.name+": support rule written for blocking payment above 10000 from guests. Process left to chain with rule 6.");
this.customerType = "guest";
cb();
}
},
/**** Rule 7 ****/
Expand All @@ -111,14 +117,15 @@ var rules = [
"priority":5,
"on":1,
"condition":
function(fact) {
return fact && fact.appCode && (fact.appCode == "MOBI4");
function(fact,cb) {
return cb(fact && fact.appCode && (fact.appCode == "MOBI4"));
},
"consequence":
function() {
function(cb) {
console.log("Rule 7 matched for "+this.name+": turn on this rule to block the payment from a specific app. Reject Paymant.");
this.result = false;
this.process = true;
cb();
}
},
/**** Rule 8 ****/
Expand All @@ -128,14 +135,15 @@ var rules = [
"priority":2,
"on":1,
"condition":
function(fact) {
return fact && fact.eventRiskFactor && (fact.eventRiskFactor < 5);
function(fact,cb) {
return cb(fact && fact.eventRiskFactor && (fact.eventRiskFactor < 5));
},
"consequence":
function() {
function(cb) {
console.log("Rule 8 matched for "+this.name+": if the event is top priority event, then do further checks else leave. Accept payment as low priority event.");
this.result = true;
this.process = true;
cb();
}
},
/**** Rule 9 ****/
Expand All @@ -145,7 +153,7 @@ var rules = [
"priority":3,
"on":1,
"condition":
function(fact) {
function(fact,cb) {
var allowedRegexp = new RegExp('^(?:' +
[
"10.X.X.X",
Expand All @@ -156,13 +164,14 @@ var rules = [
"74.23.211.92"
].join('|').replace(/\./g, '\\.').replace(/X/g, '[^.]+') +
')$');
return fact && fact.userIP && fact.userIP.match(allowedRegexp);
return cb(fact && fact.userIP && fact.userIP.match(allowedRegexp));
},
"consequence":
function() {
function(cb) {
console.log("Rule 9 matched for "+this.name+": if the ip fall in the given list of formats, then block the transaction. Rejecting payment.");
this.result = false;
this.process = true;
cb();
}
}
];
Expand Down