-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Strange NPE issue #500
Comments
@EthanEChristian we made a change in our java code that seems to have resolved the NPE issue, but now we have an infinite loop of this rule firing after the
I guess this will eventually lead to another memory leak |
Seems like you may have created a "logical loop" in with regards to the truth maintenance system (aka. TMS). There is a directly related gist of mine here on the logical loop situation. This post I wrote a while back discusses something similar if the problem becomes more of a "logical update" to facts: https://www.metasimple.org/2017/12/23/clara-updating-facts.html |
@mrrodriguez thanks "tocayo" |
Still struggling here @EthanEChristian @mrrodriguez ....decided to take a different approach.... Rather than creating the VolumeAccumulation facts from clara, now I'm inserting them (364 of them) from the calling java code, before calling fireRules. And now my rule looks like this:
However, it seems as if the retract isn't actually working because I'll see a burst of 364 log statements with every subsequent call to fireRules from further processing the java code does. I'm only expecting to see 364 log statements adn nothing more since each fact that is handled should be retracted, and should never need to be processed again. Thoughts? |
@victorrodrigueznadq I understand the problem statement here. I think I need to see a bit more about your external process though. Could you show at least an example of the sequence of calls you are making from one fireRules to the next, also including how you are inserting the initial facts into the session. |
Sure @mrrodriguez ....creating the session...
Inserting some reference data into the session that will persist across latter calls to fireRules...
Adding more reference data, that again will persist across latter calls to fireRules...
Creating working memory array from session...
That session gets passed into a back pressure controller (and assigned to baseClaraRulesSession) that we have and in there we create a worker as follows:
Then we call the call method on the worker and from there is where fireRules will be called..
Inside the call method we loop through the transactions we are processing insert one, call fireRules, and retract it....
That's it. |
sorry, we insert lists there at the end. could be one or more. |
@victorrodrigueznadq Thanks for the details. That helps see more of the complete picture. In your original problem statement, you mentioned that you are inserting 364 of these |
@mrrodriguez they are inserted during one of the two reference data insert loops. |
@mrrodriguez we are currently actrively taking measures to work around this, but we need to understand how things like retract and insert work so that we know what's going on. if we try to retract something and it really isn't retracted, we'd like to understand why. things that used to work fine in drools aren't working as expected in clara. |
Ok, that makes sense. I will try making a small example to demonstrate this type of retraction. As a bit of an aside: I also came from a Drools background. There are some key differences in Clara vs Drools that are worth noting. I will try putting of a few of these here (from memory) that hopefully are accurate:
|
Thanks @mrrodriguez ! What, exactly, does immutable working memory mean? Does it mean you can't and/or shouldn't insert into or retract from it in the RHS? Does it mean that you can't and/or shouldn't call setters on any facts that caused a rule to fire? In Drools, we used flags to prevent any further processing of a fact, but that also isn't working as expected in Clara. Instead of the LHS conditions that check for the flag not being set, we have to also add additional checks in the RHS of our Clara rules to again check that the flag isn't already set. Example: LHS: RHS: Is there a better way to accomplish the same thing in Clara? (i.e. prevent further other rules from firing for a given fact) |
For this part @victorrodrigueznadq I will put an example below of a setup that seems similar to the one you describe (very simplified) to use a I put it in this gist for easier reference later: https://gist.github.com/mrrodriguez/87053edaca5ae4b3c547303bb49e77f9 Is there a chance that the object type |
@mrrodriguez as a matter of fact, it has neither equals nor hashCode. Is it important, in Clara, for facts to have these defined? |
When I said that working memory is immutable I mean that when you externally insert/retract facts and/or fire rules you get a new working memory state reference back. The original state is not mutated, ie. it is not "updated in place". This is done efficiently internally and the working memory state data structures share a lot of memory (via Clojure's built-in persistent immutable data structures). This means you must always be sure to use the return value when calling these methods too since that is where the change happens. You bring up something else interesting here though, which is mutating facts that are in working memory. Clara does assume that you are not mutating facts in working memory. They are treated as pure values that do not change. This means you should not call setters on objects that are held in working memory. Changing a fact should be modeled in some other way like mentioned in the approach (1) or (2) in this post https://www.metasimple.org/2017/12/23/clara-updating-facts.html In Drools you are not supposed to arbitrarily mutate facts either I believe. I think it has special RHS syntax perhaps to let the engine know you are "modifying" a fact. Clara doesn't have this. It is an interesting feature, but not something we've pursued before. It is a simpler and more pure model to have the immutability. There also become a lot of useful properties that come with having immutable facts and an immutable working memory structure. I think for your case described above you could model it with an intermediate fact that represented the "flagged fact". You'd use more rules to model the situation that causes a fact to become flagged. I don't have a lot of context there to show you more concrete, but hopefully the blog references help. |
In this particular case, your rule called retract on the same fact binding that you bound in the LHS, so should still work anyways - they are identical object references so should be considered equal. I think in general though that assumption worries me. Clara uses tends to consider facts to have "value semantics". I've mentioned part of this already before, that means they are expected to be immutable when in working memory. The other part of that is they are supposed to have equals/hashCode behavior that reflects your expectation of when you are describing the "same fact". If you do not have a equals/hashCode than you are only able to use object identity to determine if a fact is the same in working memory. Perhaps that is what you want, but I think often that is not the case. |
This is my original clara rule, which was converted from a drools implementation:
I was having a memory leak because we didn't have a check to prevent the same VolumeAccumulation records from being created and inserted over an over again each time the rules were fired. So then I added a :not check. I kept betting NPE exceptions complaining about firmIdentifier being null, so I kept adding more and more (some?) checks to ensure, supposedly, that that couldn't never happen, but thusfar, I've been unable to erradicate that NPE exception. Here's what the rule currently looks like (added (insert! volumeAccumulation) to the end of the RHS):
And, here's the exception:
Any ideas what could possibly be going on?
The text was updated successfully, but these errors were encountered: