6

It is possible within the rules engine to create a scenario where a set of rules cause an infinite loop. Take for example the following rule that has a When Condition to itself:

enter image description here

This example is very simple but when you have some very complex rules then this loop isn't obvious to the Content Editor or Developer (e.g. the loop could be caused by 4 or 5 chained rules).

This loop causes a Stack Overflow exception which brings the entire server down.

Has anyone written anything to detect these loops or found another way to solve this?

Unfortunately looking at the RuleFactory class it is static so can't be replaced. I was hoping to maybe use something like the RuleStack class but the RuleStack is not global to all rules, a new one is created when the WhenCondition is called.

Any ideas? We are using Sitecore 8.1 U3.

1
  • What sort of items are these? Is it a conditional rendering issue or some sort of custom use of the rule engine? Commented Jan 20, 2017 at 14:18

1 Answer 1

2

It might be possible to achieve this with a little hackery (if you can stomach it)...

Unfortunately, as you correctly identified, the RuleFactory is static, and therefore you can't replace it directly. However, in the version of Sitecore you're using, it appears that the private Cache field in the RuleFactory static class acts as a gateway for accessing all rules in the system. This in turn uses an underlying Sitecore Cache named 'rules'.

So, what you might be able to do is create a new processor in the <initialize> pipeline to replace the 'rules' Cache in Sitecore with your own implementation. Every time an item (RuleList<T>) is added to the cache, you should simply wrap it in a custom RulesList<T> implementation.

The purpose of this wrapper RulesList<T> implementation would be to override the virtual Run() method, which should allow you to keep track of a thread-local stack for each time a rule is used, allowing you to create a heuristic algorithm for detecting cycles.

Regarding the heuristic model: I don't think you'll be able to deterministically detect a cycle in a rule chain, simply because doing so would require you to solve the Halting Problem, so simply counting the depth of the current stack (and bailing at a certain number) may be your only option.

Of course, in Sitecore 8.2, replacing the RuleFactory is trivial :)

2
  • 1
    I have done this kind of hackery before other problems and it never feels nice. Unfortunately I don't think this will work because the cache only gets requests for a rule and never knows about the disposal/end of a rule. This means that the counter will always count up with no way of being reduced. Two independent sets of rules run on the same thread will only ever increase the number a probably mean the second set of rules will throw the depth exception even though they aren't that deep. Commented Jan 20, 2017 at 7:23
  • Hey Mike, unless I'm mistaken (which is entirely possible), I believe you should be able to Push & Pop the stack by wrapping each rule contained within the RulesList<T> with a custom Rule<T>. It's an incredibly tedious process, but you should be able to 'hide' any members of the underlying Rule<T> type with the new keyword and Push and Pop within the overridden method (specifically the Evaluate method in the Rule<T> class). Commented Jan 20, 2017 at 20:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.