-
Notifications
You must be signed in to change notification settings - Fork 22
Activity
Forgive me if you already knew the answer. I want to answer this because I want to understand more about this library and maybe this will be helpful to someone else
To answer the question "is it really per entity?" I would say yes but I wouldn't use the term entity since the word isn't used anywere in this library. What we have are id , attribute , and value. The {:then compare-fn} block is the comparison of the value of the attribute of the same id.
you can see the behaviour more clearly by using the debugger outlined in the readme like this (as babashka snippet since this library is bb-compatible).
(require '[babashka.deps :as deps])
(deps/add-deps '{net.sekao/odoyle-rules {:mvn/version "1.3.1"}})
(require '[odoyle.rules :as o])
(defn debugger-wrapper [rule]
(o/wrap-rule rule
{:what
(fn [f session new-fact old-fact]
(println "the rule" (:name rule) "is comparing old:" old-fact "and new:" new-fact)
(f session new-fact old-fact))
:then
(fn [f session match]
(println "firing" (:name rule))
(f session match))}))
(def session (->> (o/ruleset
{::foo
[:what
[id ::x x {:then not=}]
:then
(o/insert! (inc id) {::x 10})]})
(map debugger-wrapper)
(reduce o/add-rule (o/->session))))
(-> session
(o/insert 0 {::x 10})
(o/fire-rules {:recursion-limit 1})
(o/query-all))
you will see that the print output will be
#'rules/debugger-wrapper
the rule :rules/foo is comparing old: nil and new: #odoyle.rules.Fact{:id 0, :attr :rules/x, :value 10}
firing :rules/foo
the rule :rules/foo is comparing old: nil and new: #odoyle.rules.Fact{:id 1, :attr :rules/x, :value 10}
firing :rules/foo
the rule :rules/foo is comparing old: nil and new: #odoyle.rules.Fact{:id 2, :attr :rules/x, :value 10}
firing :rules/foo
the rule :rules/foo is comparing old: nil and new: #odoyle.rules.Fact{:id 3, :attr :rules/x, :value 10}
clojure.lang.ExceptionInfo: Recursion limit hit.
This may be an infinite loop.
The current recursion limit is 1 (set by the :recursion-limit option of fire-rules).
Cycle detected! :rules/foo is triggering itself.
Try using {:then false} to prevent triggering rules in an infinite loop. user odoyle/rules.cljc:549:5As you can see, what your rule does is to add a new attribute to a new id which have no attribute at all, which make not= always be true.
(though what I don't expect is that giving it {:recursion-limit 1}, the fire-rules still calls the rules 3 times. )
this code
results in this error
i expected their to be no loop because while the first insert would pass because (not= 10 1) is true, on the second (not= 10 10) would be false and it would stop. For reasons i don't understand if i hardcode the id passed to insert:
It works, this implies whats being compared, by the then block, is really it per entity. is that right?