Over the last week, I have enjoyed reading JESS in Action from cover to cover and doing my fair share of tinkering. Hopefully I now know enough about JESS to be slightly more than just dangerous. I'm evaluating JESS for the redesign of an ecommerce order validation process and trying to get a handle on the rule architecture. Does anyone have thoughts/caveats on the proposed design below?
Key considerations:
- The rule engine should allow for the validation/creation of orders through two channels--web site and web service. From a rule perspective, the difference between the two channels is that a web service receives all of the data for validation at a single time and the web site breaks the validation up into smaller steps (User Validation, Item validation, Payment validation, Delivery validation).
- The entities for the input data in both channels are the same (order header info, item info, payment info, shipping info, etc.)
- all entities may not be present for a given run. E.g. item validation will be performed before payment information has been attained from the web site.
- The number of users and products is in the half a million ball park.
Proposed Jess Design:
- pool Rete instances
- reset is called and static (don't change over course of engine lifetime) facts are asserted before a Rete is added to the pool
- use backward chaining to support rules based on previously persisted user attributes and product attributes
- use modules to group related (based on dependency and functional area) rules
- use the focus stack to determine module firing sequence and rule set to fire for a run (channels would have different focus stacks before calling run)
- store each module in a separate file to simplify maintenance and change control
- only dynamic (change with each run) facts in the engine are javabeans definstanced before the run
- a small number of "working facts" may be created during the course of the run
- retract all dynamic and working facts before returning Rete to the pool
Questions:
Instead of retracting facts, I could call reset at the end of each run and then assert my static facts. I am assuming that the greater the amount of static facts, the worse this option will perform. Is that true? The static facts would be coming from a database. Could I use deffacts or something similar to ensure that reset quickly returns to an initial state with around 1000 static facts?
I am assuming pooling Rete instances is the best approach since, the number of static facts won't consume an excessive amount of memory for each instance. I realize that I could design the facts and rules so that a single Rete instance would suffice. My understanding of the single Rete's drawbacks is that I have to worry about thread blocking and the rules will be slightly more complex. Are there any other important distinctions between the two approaches?
Thanks for any help and please be kind to newbie!
Andy Powell
