Rikkola opened a new pull request, #7116:
URL: https://github.com/apache/incubator-kie/pull/7116
## Problem
A rule guarded by `exists(A() and not B())` silently stops firing when a
rule in a **different package** also uses `exists(A() and ...)`. No build
error, no warning — the rule is simply never activated.
Reproducer (four packages):
```drl
// repro.a
rule "produce-shared-fact" when Seed() then insert(new SharedFact()); end
// repro.b ← stops firing
rule "subject" when exists(SharedFact() and not NegatedFact()) then
insert(new Result()); end
// repro.c ← its presence breaks the rule above
rule "sibling" when exists(SharedFact() and OtherFact()) then end
```
`NegatedFact` and `OtherFact` are never inserted, so `subject` must fire. It
does on 9.44.0.Final. It does not on 10.0–10.2 and current main.
Related: apache/incubator-kie#7109
## Root cause
Two commits combine to produce this bug:
1. **[DROOLS-7238] Rete Buildtime Segmentation** (9b650b1) — introduced
`SegmentPrototype.splitEagerProtos` with the guard:
```java
if (proto1WasEager) { // if it wasn't eager before, nothing can be eager
after
```
2. **Split Beta Nodes** (2aa4b18) — introduced `ExistsRight`/`NotRight`
wrapper nodes, enabling cross-subnetwork `JoinNode` sharing.
Packages build sequentially. When `repro.b` is added, its inner segment
contains both `JoinNode(SharedFact)` and `NotNode`. The joint presence of both
suppresses the eager requirement (`requiresAnEagerSegment() = false`), so the
segment is **not marked eager**. When `repro.c` is added later, `processSplit`
splits the shared segment:
- proto1 = `[JoinNode(SharedFact)]` — **not eager** (`proto1WasEager =
false`)
- proto2 = `[NotNode, TTON_subject]` — **eager** (NotNode without its
JoinNode)
`splitEagerProtos(proto1WasEager=false, proto2, TTON_subject)` hits the
guard and exits immediately, so **proto2 is never registered** in
`TTON_subject.eagerSegmentPrototypes`. At session creation,
`initializePathMemory` finds an empty eager list → the `[NotNode,
TTON_subject]` segment is never created → the NotNode's "start linked" state is
never propagated → `ExistsNode_subject` is permanently unlinked → the outer
rule never fires.
## Fix
Add an `else if` branch in `splitEagerProtos` for the case where `proto1`
was not eager but `other` (proto2) requires eager:
```java
} else if (other.requiresEager()) {
// proto1 was not eager, but the split produced an eager proto2.
SegmentPrototype[] eager = endNode.getEagerSegmentPrototypes();
SegmentPrototype[] newEager = new SegmentPrototype[eager.length + 1];
System.arraycopy(eager, 0, newEager, 0, eager.length);
newEager[newEager.length - 1] = other;
endNode.setEagerSegmentPrototypes(newEager);
}
```
## Test
`ExistsWithNotSubnetworkCrossPackageTest` — 5 test methods × 2 configs
(CLOUD_IDENTITY + CLOUD_EXEC_MODEL) = 10 parameterised instances:
| Test | Purpose |
|------|---------|
| `subjectFiresWhenSiblingInDifferentPackage` | Direct regression:
cross-package sibling, insert reproducer |
| `subjectFiresWhenSiblingInDifferentPackageWithRuleChaining` | Rule-chained
insert variant |
| `subjectFiresWhenSiblingInSamePackage` | Same-package sibling must still
fire (control) |
| `subjectFiresWithoutSibling` | No sibling at all must still fire (control)
|
| `subjectFiresWithPlainJavaClasses` | Plain Java classes, not
declare-type-specific |
All 10 pass after fix. 310 tests across 9 regression suites all green
(including the new `SegmentSplitAccumulateTest` from #7110).
--
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]