Fork me on GitHub
#clara
<
2018-05-23
>
jdt15:05:32

Hello all, I've been trying a bit of clara-rules to assess it for a project. I'm having some trouble with with-tracing though.

jdt15:05:54

If I omit the with-tracing call fire-rules does its work. If I add with-tracing before it, fire-rules no longer works (none of my rules are fired).

jdt15:05:18

If I move with-tracing before (insert ...) I get lots of traces.

jdt15:05:42

What am I doing wrong?

jdt15:05:04

I'm using [com.cerner/clara-rules "0.18.0"]

jdt15:05:14

and clojure 1.9

jdt15:05:11

I don't want to trace the rete activity on the initial insert, just the activities of fire-rules and the working memory alterations there.

mikerod17:05:59

@dave.tenny it’s an interesting point you bring up, but I don’t think it really makes sense to only “partially” have with-tracing enabled

mikerod17:05:22

All session interactions prior to fire-rules are susceptible to lazy evaluation and batching.

mikerod17:05:52

In general, I’d stress to not rely on any stateful information of a session that has had inserts/retracts performed on it, but no fire-rules

jdt17:05:19

Heh, not sure I was trying to make a point. I didn't understand why fire-rules didn't work based on the placement of with-tracing. Since my rules weren't firing.

mikerod17:05:22

I’d actually rather it be the case that the API threw an exception if you tried to query or do something like with-tracing when it was in an inconsistent/lazy/batched state prior to fire-rules

jdt17:05:55

Naively (since I am naive here), I just figured my session would be upgraded to do tracing.

mikerod17:05:58

It’s an interesting point regarding the limitations of with-tracing and lazy/batched insert/retract behavior I meant

mikerod17:05:31

I certainly haven’t dug into details to diagnose your specific issue, but I’d imaging the with-tracing added late, after the insert missed some listener information it needed

jdt17:05:33

So how should I be using with-tracing here?

mikerod17:05:58

Only add it when you have a session that doesn’t have insert, insert-all, or retract calls possibly still pending on it

mikerod17:05:10

so either (a) right after your mk-session, or (b) right after a fire-rules

jdt17:05:50

I'm doing insert! and retract! in my rule RHS's, but but the only insert was as shown, before the with-tracing call.

mikerod17:05:53

but you won’t get tracing “only for the fire-rules actions that took place, you’ll get a complete picture, you can looking into tracing details to find out specific things, like facts inserted due to rules firing etc (at least to some degree)

mikerod17:05:49

@dave.tenny you did this?

(-> (mk-session)
	(with-tracing)
	(insert ...)
	(fire-rules))

jdt17:05:26

Yes, that way I get tracing, and fire-rules works as expected.

mikerod17:05:52

that’s the way to use it

jdt17:05:05

ok, thanks

mikerod17:05:20

So I don’t know what your question is beyond that and beyond what I said about it being misleading in the API to let you add it at arbitrary points

jdt17:05:37

I'm trying to get the network activity after the initial bulk load of facts.

mikerod17:05:42

I think it’d be better to reject an attempt to add it at the “wrong times”, enhancement

jdt17:05:55

And when I do that, by moving the trace after the facts are loaded, my fire-rules don't work.

mikerod17:05:04

yeah, it doesn’t work on that principle

jdt17:05:13

ok, good to know, still learning

jdt17:05:43

That begs the question of when it is safe to use it. Say I make a session, load data, run rules, query results. Then I want to change the data in the session and run it again with tracing. Will it work then? Or is it always safe to use with-tracing after fire-rules calls?

mikerod17:05:54

I’m not actually sure there is a way to look at the listener information and know the different between a fact inserted externally, via insert and a fact inserted from a RHS, via insert!. I don’t know of one off hand.

mikerod17:05:52

> Or is it always safe to use with-tracing after fire-rules calls? I think so and expect so. If it has issues, it’d be interesting to discuss them. Also, I don’t have any reason to think that it should ever change the semantics of the rules, you may just get bad/invalid tracing results

mikerod17:05:07

Earlier you said it caused your rules to not fire correctly, I’m skeptical on that

mikerod17:05:18

the tracing may not have accurately reported the rule firings, but they probably still fired

mikerod17:05:36

you can test that assumption, by adding a defquery to your session

jdt17:05:45

re: firing, my rules had printlnin them, which didn't print when the with-tracing was done after the insert.

mikerod17:05:48

and then using a query on the RHS insert! facts that you think didn’t get inserted

mikerod17:05:04

Yeah, if you can reproduce that case at all, that’d be valuable

jdt17:05:15

Okay, well it's pretty simple, I'll see what I can do.

mikerod17:05:23

I don’t expect with-tracing to be able to interfere with evaluation in that way

mikerod17:05:51

yeah, so with-tracing does appear to wipe out pending work

4
juxt 4
mikerod17:05:04

so you’re right, it’d cause trouble like you saw

mikerod17:05:14

after fire-rules should be safe - there is no pending work

mikerod17:05:40

it may be a “good thing” that with-tracing wipes out pending work since it makes a session that it can actually trace

mikerod17:05:05

well, idk about that, it’s just a weird situation hah - either needs docs or to throw an exception or something I think 🙂

jdt17:05:14

Sounds like the documentation should be a bit clearer about restrictions though to avoid noob run-ins like mine.

mikerod17:05:21

Yes, it is too mysterious

jdt17:05:30

I'm just trying to wrap my head around other things, like the Truth Maintenance capabilities that may or may not have been present in the OPS5 systems I was using 30 years ago. I'm pretty rusty at this. Retracting the preconditions that led to the state of the RHS doing the retraction seems to mean I need to fire rules, query my reults on the session afterward, make changes, then rinse-lather-repeat, where it used to be I'd do more stuff in the RHS clauses. Thus my attempts at ... modular ... tracing.

jdt17:05:42

So a bit of catching up for me. I'm investigating clara for the job dispatch logic of a new scheduler I'm writing.

jdt17:05:59

Meanwhile thanks for the help.

mikerod17:05:12

@alex-dixon has done a lot with Clara’s tracing by extending it for his own purposes in the #precept library. Perhaps you can find some inspiration there.

alex-dixon17:05:54

I think I ended up using the listeners namespace only. I forget at the moment how it relates to clara’s tracing

mikerod17:05:22

@alex-dixon oh, tracing just organizes the data coming from listeners I believe

mikerod17:05:08

wait no, tracing is a default impl over listeners

alex-dixon17:05:14

Ah ok. That what I seem to remember but thought I may have been confusing it with explanations

mikerod17:05:19

(sort of the same as I said)

mikerod17:05:29

yeah, explanations/inspect are above all that

alex-dixon17:05:32

Yet listeners is very user friendly imho. Though I may have ran into some private things I wanted public

alex-dixon17:05:44

It is nice to have it boxed up and ready to use just at the same time the listeners ns is highly usable in and of itself I mean

alex-dixon18:05:52

@dave.tenny If you end up poking around Precept at all I’d recommend the issue 19 branch

1️⃣ 8
9️⃣ 8
jdt18:05:51

Will keep that in mind, so far have only looked at Clara-rules.

👍 8
jdt19:05:28

(defquery my-query ...) followed by a what is typically another function wrapping the query with a call to (query session my-query) gets old. Is there w away to do a lexical defquery equivalent at the point I'd call query?

zylox19:05:57

defquery more or less sets up an endpoint in your rules network, it needs to be known before hand

👍 4
zylox19:05:34

query goes and grabs the list it generates at when things are fired, it doesnt go calculate it then (to my knowlege)

👍 4
zylox19:05:21

you can, and i would not reccomend this outside of development, create a defquery for Object that just grabs everything in the session and then filter that as you see fit.

👍 8
mikerod20:05:35

@dave.tenny I’ve only partially read your example so far, but one immediate piece of feedback, don’t query until after fire-rules

mikerod20:05:53

think of query the same as with-tracing earlier, you have to only do it on “consistent” states of a session

mikerod20:05:30

Clara does some delayed evaluation for performance reasons. Any inserts/retracts that occur prior to a fire-rule cannot be relied upon and I’d consider the session to be in an “undefined” state

mikerod20:05:41

I’d actually prefer Clara to change for query to either (a) throw exception if called prior to a fire-rules or return something that indicates it is not ready yet.

mikerod20:05:50

Clara takes advantaged of batched insertion and also potentially a few other things, so it does not eagerly perform things like insert or retract. The evaluation is typically pushed to batch up the facts propagating through the network. This can play a major role in performance.

mikerod20:05:49

You mentioned OPS5, which you likely wouldn’t have seen behavior like this long ago. It is more common now. Drools is a popular JVM-based rules engine and it similarly has delayed evaluation of things prior to rule firing due to similar concerns.

mikerod20:05:27

This issue seems to somewhat often trip people up though. So I don’t think it is clear enough.

mikerod20:05:13

For your second question > ;why are my counters still there, I retracted them? I think it is because (query % counters) doesn’t return what you are thinking it does

mikerod20:05:52

It doesn’t return the bare counter fact, instead it returns a bindings map from the query, so it returns something like:

{:?counter <the counter fact>}

mikerod20:05:32

so you’d probably have to do something like

(#(apply retract % (map :?counter (query % counters))))

jdt20:05:36

Oh sorry, forgot to include the output

jdt20:05:40

It works, just not as expected

jdt20:05:43

Here comes the output

mikerod20:05:58

that output looks consistent with the explanation I just gave

mikerod20:05:03

so try to apply the things I mentioned

jdt20:05:17

Ah, that fixes it

jdt20:05:26

(map :?counter ...)