diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index e27fd28a..c5714cc1 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -11,6 +11,7 @@ Community - David Goeke [@dgoeke] - Dave Dixon [@sparkofreason] - Baptiste Fontaine [@bfontaine] +- Jose Gomez [@k13gomez] [@rbrush]: https://github.com/rbrush [@mrrodriguez]: https://github.com/mrrodriguez diff --git a/src/main/clojure/clara/rules/engine.cljc b/src/main/clojure/clara/rules/engine.cljc index a727feb4..d7af0f4a 100644 --- a/src/main/clojure/clara/rules/engine.cljc +++ b/src/main/clojure/clara/rules/engine.cljc @@ -144,30 +144,47 @@ (retract-elements [transport memory listener nodes elements]) (retract-tokens [transport memory listener nodes tokens])) +(declare get-conditions-and-rule-names) +(declare single-condition-message) + +(defn- throw-condition-node-exception + "Adds a useful error message when executing a constraint node raises an exception." + [{:keys [cause node]}] + (let [conditions-and-rules (get-conditions-and-rule-names node) + condition-messages (->> conditions-and-rules + (map-indexed single-condition-message) + (string/join "\n")) + message (str "Condition exception raised.\n" condition-messages)] + (throw (ex-info message + {:conditions-and-rules conditions-and-rules} + cause)))) + (defn- propagate-items-to-nodes [transport memory listener nodes items propagate-fn] (doseq [node nodes :let [join-keys (get-join-keys node)]] - - (if (pos? (count join-keys)) - - ;; Group by the join keys for the activation. - (doseq [[join-bindings item-group] (platform/group-by-seq #(select-keys (:bindings %) join-keys) items)] - (propagate-fn node - join-bindings - item-group - memory - transport - listener)) - - ;; The node has no join keys, so just send everything at once - ;; (if there is something to send.) - (when (seq items) - (propagate-fn node - {} - items - memory - transport - listener))))) + (try + (if (pos? (count join-keys)) + + ;; Group by the join keys for the activation. + (doseq [[join-bindings item-group] (platform/group-by-seq #(select-keys (:bindings %) join-keys) items)] + (propagate-fn node + join-bindings + item-group + memory + transport + listener)) + + ;; The node has no join keys, so just send everything at once + ;; (if there is something to send.) + (when (seq items) + (propagate-fn node + {} + items + memory + transport + listener))) + (catch #?(:clj Exception :cljs :default) e + (throw-condition-node-exception {:cause e :node node}))))) ;; Simple, in-memory transport. (deftype LocalTransport []