[rules-users] Better way to run each rule once?

Dave Schweisguth dave at schweisguth.org
Fri Oct 9 17:46:32 EDT 2009


Fellow Droolers,

On Fri, Oct 09, 2009 at 09:33:38AM +0100, Anstis, Michael (M.) wrote:
> From: Dave Schweisguth <dave at schweisguth.org>
> > Each of our rules modifies the fact it matches. We'd like to run each of
> > those rules exactly once, not reactivating them when a fact changes.
> > [...]
> 
> You could look into using a sequential RETE network
> 
> http://blog.athico.com/2007/07/sequential-rete.html 
> 
> http://www.redhat.com/docs/manuals/jboss/jboss-soa-4.2/html/JBoss_Rules_
> Manual/ch02s05s10.html
> 
> But as Greg suggests, better understanding your use-case might furnish
> other ideas.

First, SequentialOption seems to be exactly what I was looking for; many
thanks. I set it and removed my AgendaFilter and my tests all pass, and
faster.

Nonetheless here's the use case for those interested: My principal facts are
objects which I'll call Things which have an ID, a bunch of properties
(unmodifiable fields), and a bunch of named numeric attributes which to keep
things simple I'll treat as a Map<String, Long>. The goal of the rules is to
calculate the attributes.

A typical rule looks like

    when thing: Thing(description matches ".*leaves.*")
    then modify (thing) { attributes.green = 100 }

Clearly one wants a rule like this to run only once. Since in a given rules
session there are multiple rules like this, no-loop wasn't sufficient; after
one rule fired it would activate another already-run rule on the same Thing,
and then vice versa, forever. With all the rules in the same ruleflow group
lock-on-active was too much in that it allowed only one rule to run. (It
occurs to me now that I might have made each rule no-loop and run it in a
new session; fortunately I don't seem to have to try that now.)
SequentialOption seems to fit this use case perfectly. Of course I'll be
interested if anyone has a still better way to address it.

Side note: Wolfgang, you were wondering why my AgendaFilter needed the
Identifiable interface. You can see from the above that if I wanted to
prevent a rule from firing more than once on the same Thing, I'd need to
recognize the Thing after the rule fired and its attributes (which affect
.equals and .hashCode) changed. It occurs to me now that I could just have
used object identity (==), since rules don't assert new Things. A form of
equals which considered only Thing's ID would also have been more correct
than my hashCode-like solution. Fortunately I no longer need this approach
at all.

Thanks all for your interest and support!

Cheers,

-- 
| Dave Schweisguth                           http://schweisguth.org/~dave/ |
| Home: dave at schweisguth.org            Work: http://www.nileguide.com/ |
| For compliance with the NJ Right to Know Act: Contents partially unknown |



More information about the rules-users mailing list