CacheControl / json-rules-engine

A rules engine expressed in JSON
ISC License
2.6k stars 461 forks source link

Is it possible to make sure that a fact triggers at most one rule? #343

Closed pachecolp closed 1 year ago

pachecolp commented 1 year ago

I have a set of hundreds of rules and need to find if a fact triggers one of them, but it shouldn't trigger more than one (this would be a fallback rule, with very relaxed criteria). How could I implement that?

chris-pardy commented 1 year ago

When you run the rules engine the rule results return the full set of conditions that were executed with the result of those executions so if your rule was:

{
   "conditions": {
       "any": [
            {
                  "fact": "relaxedValue",
                  "operator": "equal",
                 "value": true
            }
        ]
   },
  "event": {
       "type": "fallback"
  }
}

in your rule results you'd see:

{
   conditions: {
      all: [
        {
             fact: "relaxedValue",
             operator: "equal",
             value: true,
             result: true / false
        }
      ]
  }
}

Given this it sounds like there's a few things you could do:

Static analysis

Basically if you have all the rules and you know only 1 rule should be triggered when this fact has a certain value or certain values, then you should be able to write something that verifies this by parsing the json and looking for places where something would successfully evaluate.

Run the rules engine

Use different values for the fact that you're looking to test. Ensure that in the cases where it should emit the fallback event that's the only event emitted. If you want to verify that the fact will never trigger a rule to pass you'll need to look at the failed rules and ensure that any condition which mentions the fact has a result of false.

pachecolp commented 1 year ago

Thank you, @chris-pardy! What I ended up doing was using priority to sort the results, picking the top one and adding a warning message in the log if a fact matches more than one rule, just in case the priority might need fine tuning.