drccrd opened a new issue, #7109: URL: https://github.com/apache/incubator-kie/issues/7109
### Describe the bug ## Trigger conditions See reproducer attached. 1. A rule R1 whose LHS contains an `accumulate` is attached to the network while its LeftInputAdapterNode (LIA) is not yet shared, so its whole path is one segment. 2. A rule R2 sharing that LIA is attached afterwards through the incremental path (`ReteooRuleBuilder.attachTerminalNode` -> `PhreakBuilder.addRule` -> `EagerPhreakBuilder.Add.processSplit`), which splits R1's segment at the LIA. 3. At runtime a left tuple reaches the accumulate node first (result constraint false, nothing propagated) and a matching right fact arrives later. Condition 2 is met during a normal `KieContainer.getKieBase()` build for every package **except the largest one**: `KnowledgeBaseImpl.addPackages` sorts packages by rule count (descending) and adds them one package at a time; only the first package gets its segment prototypes created in bulk after all its rules are attached (`kBaseInternal_addRules`), every later package is added rule by rule with segment splitting. Within a package, rule order follows DRL file order, and the in-memory KieFileSystem iterates files in `HashMap` order (`MemoryFileSystem.fileContents`), so adding unrelated files can change which rule is attached first. ## Root cause `SegmentPrototype.splitProtos()` renumbers the node position bits of the new (second) segment by calling `MemoryPrototype.setNodePosMaskBit()` on each memory prototype. `AccumulateMemoryPrototype` delegates `populateMemory()` to a wrapped `BetaMemoryPrototype` and copies the *wrapped* prototype's bit into the accumulate node's `BetaMemory`, but `setNodePosMaskBit()` only updates the wrapper's own field. The accumulate node's `BetaMemory` is therefore created with its pre-split bit (2 = second node of the old segment) instead of 1 (first node of the new segment). At runtime `BetaNode.assertObject` -> `BetaMemory.linkNode/setNodeDirty` flags bit 2 (the slot of the node after the accumulate). `SegmentCursor.moveToNextAvailableSegment` skips nodes whose dirty bit is clear, so the accumulate node's staged right tuples are never processed and the rule never fires. Everything looks healthy from the outside: the path is linked, the agenda item is not queued and the executor is not dirty. Files (drools-core): `org.drools.core.reteoo.SegmentMemory` (`SegmentPrototype.splitProtos`, `AccumulateMemoryPrototype`), `org.drools.core.phreak.EagerPhreakBuilder` (`splitSegment`), `org.drools.core.phreak.SegmentCursor` (`moveToNextAvailableSegment`), `org.drools.core.reteoo.BetaMemory`. A second, cosmetic inconsistency of the split path: `SegmentPrototype.splitBitMasks` assigns `segmentPosMaskBit = previous << 1` to the new segment even when its `allLinkedMaskTest` is 0, whereas the bulk build (`BuildtimeSegmentUtilities.createLeftTupleNodeProtoMemories`) assigns 0 in that case. ### Expected behavior The accumulate node always gets marked as dirty, even if shared, and re-evaluates as required. ### Actual behavior The node is never re-evaluated. This was visible after the eager evaluator was changed to opt-out in drools 10.0.0 ### How to Reproduce? Link following. ### Output of `uname -a` or `ver` _No response_ ### Output of `java -version` _No response_ ### GraalVM version (if different from Java) _No response_ ### Kogito version or git rev (or at least Quarkus version if you are using Kogito via Quarkus platform BOM) 10.0.0, 10.1.0, 10.2.0 ### Build tool (ie. output of `mvnw --version` or `gradlew --version`) _No response_ ### Additional information _No response_ -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
