json-rules-engine icon indicating copy to clipboard operation
json-rules-engine copied to clipboard

Caching issue with engine

Open iprasla opened this issue 3 years ago • 1 comments

I am having a use case scenario where I have a very simple rule that is run against provided fact(s). When I run the engine, I notice that on success event gets called multiple times hence it create duplicates. The example is below:

const engine = new Engine();

const countryRule = {
  conditions: {
    all: [
      {
        all: [
          {
            fact: 'country',
            operator: 'equal',
            value: 'IN',
          },
          {
            fact: 'continent',
            operator: 'equal',
            value: 'Asia',
          },
          {
            fact: 'state',
            operator: 'in',
            value: ['KERALA', 'PUNJAB', 'GUJARAT'],
          },
        ],
      },
    ],
  },
  event: {
    type: 'rule-event-india',
    params: {
      message: 'The rule satisfy for India',
        },
  },
  priority: 75,
};
engine.on('success', (event, almanac) => {
matchedResults.push(event.params.message);
 });

engine.on('failure', ......) ....

// feedFactsToEngine is called by an API method
const feedFactsToEngine = async (feeds) => {
  engine.addRule(countryRule);
  engine.addFact('finders', '', { cache: false });
  await Promise.all(feeds.map(f => engine.run(f)));
  
  return matchedResults;
};

iprasla avatar Sep 28 '21 17:09 iprasla

You are misunderstanding cache.

All facts are cached on any given run by default. This is important if your facts are async functions and you want to reuse them in multiple rules, but not call the functions each time (the first call to the async function will be cached and reused amongst all rules that require it).

cache: false means - DO NOT cache the value for this fact - i.e. if I use my async fact in 3 places, make 3 async calls.

It's irrelevant in your case anyway because finders is a string, not an async function. Moreover, you're not using a fact called finders anywhere in your rules, it's unclear why you are even using it.

After all this is said, you are running the engine multiple times:

await Promise.all(feeds.map(f => engine.run(f)));

It will spit out the relevant events each time it is ran. If there are 4 feeds then you could get up to 4 results.

This is essentially a misunderstanding and you need to restructure what you're doing and/or how you're doing it.

akmjenkins avatar Oct 14 '21 13:10 akmjenkins