This is an automated email from the ASF dual-hosted git repository.

tkobayas pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie.git


The following commit(s) were added to refs/heads/main by this push:
     new a504a90d513 [incubator-kie-6906] Auto-focus in PhreakRuleTerminalNode 
does not halt the active group evaluator (#6908)
a504a90d513 is described below

commit a504a90d5139dfe99fb5b2410718a6a75128668b
Author: Toshiya Kobayashi <[email protected]>
AuthorDate: Tue Aug 25 10:11:17 2026 +0900

    [incubator-kie-6906] Auto-focus in PhreakRuleTerminalNode does not halt the 
active group evaluator (#6908)
---
 .../drools/core/phreak/PhreakRuleTerminalNode.java |  19 ++--
 .../model/codegen/execmodel/FiringOrderTest.java   | 101 +++++++++++++++++++++
 2 files changed, 113 insertions(+), 7 deletions(-)

diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakRuleTerminalNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakRuleTerminalNode.java
index ce75adef6db..01dfa7f2755 100644
--- 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakRuleTerminalNode.java
+++ 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakRuleTerminalNode.java
@@ -76,9 +76,7 @@ public class PhreakRuleTerminalNode {
                               RuleExecutor executor) {
         RuleAgendaItem ruleAgendaItem = executor.getRuleAgendaItem();
 
-        if ( rtnNode.getRule().getAutoFocus() && 
!ruleAgendaItem.getAgendaGroup().isActive() ) {
-            activationsManager.getAgendaGroupsManager().setFocus( 
ruleAgendaItem.getAgendaGroup() );
-        }
+        autoFocusIfNeeded(rtnNode, ruleAgendaItem, activationsManager);
 
         for (RuleTerminalNodeLeftTuple leftTuple = (RuleTerminalNodeLeftTuple) 
srcLeftTuples.getInsertFirst(); leftTuple != null; ) {
             RuleTerminalNodeLeftTuple next = (RuleTerminalNodeLeftTuple) 
leftTuple.getStagedNext();
@@ -166,9 +164,7 @@ public class PhreakRuleTerminalNode {
                               TupleSets srcLeftTuples,
                               RuleExecutor executor) {
         RuleAgendaItem ruleAgendaItem = executor.getRuleAgendaItem();
-        if ( rtnNode.getRule().getAutoFocus() && 
!ruleAgendaItem.getAgendaGroup().isActive() ) {
-            
activationsManager.getAgendaGroupsManager().setFocus(ruleAgendaItem.getAgendaGroup());
-        }
+        autoFocusIfNeeded(rtnNode, ruleAgendaItem, activationsManager);
 
         for (RuleTerminalNodeLeftTuple leftTuple = (RuleTerminalNodeLeftTuple) 
srcLeftTuples.getUpdateFirst(); leftTuple != null; ) {
             RuleTerminalNodeLeftTuple next = (RuleTerminalNodeLeftTuple) 
leftTuple.getStagedNext();
@@ -180,7 +176,16 @@ public class PhreakRuleTerminalNode {
         }
     }
 
-    public static void doLeftTupleUpdate(ReteEvaluator reteEvaluator, 
+    private static void autoFocusIfNeeded(TerminalNode rtnNode, RuleAgendaItem 
ruleAgendaItem,
+                                          ActivationsManager 
activationsManager) {
+        if (rtnNode.getRule().getAutoFocus() && 
!ruleAgendaItem.getAgendaGroup().isActive()) {
+            if 
(activationsManager.getAgendaGroupsManager().setFocus(ruleAgendaItem.getAgendaGroup()))
 {
+                activationsManager.haltGroupEvaluation();
+            }
+        }
+    }
+
+    public static void doLeftTupleUpdate(ReteEvaluator reteEvaluator,
                                          TerminalNode rtnNode, 
                                          RuleExecutor executor,
                                          ActivationsManager 
activationsManager, 
diff --git 
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/FiringOrderTest.java
 
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/FiringOrderTest.java
index af0623da656..ed2167e9ca1 100644
--- 
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/FiringOrderTest.java
+++ 
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/FiringOrderTest.java
@@ -59,6 +59,43 @@ public class FiringOrderTest extends BaseModelTest {
         }
     }
 
+    public static class TestFact {
+
+        private final String name;
+        private final boolean autoFocusTarget;
+        private String state = "PENDING";
+        private boolean priorityHandled;
+
+        public TestFact(String name, boolean autoFocusTarget) {
+            this.name = name;
+            this.autoFocusTarget = autoFocusTarget;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public boolean isAutoFocusTarget() {
+            return autoFocusTarget;
+        }
+
+        public String getState() {
+            return state;
+        }
+
+        public void setState(String state) {
+            this.state = state;
+        }
+
+        public boolean isPriorityHandled() {
+            return priorityHandled;
+        }
+
+        public void setPriorityHandled(boolean priorityHandled) {
+            this.priorityHandled = priorityHandled;
+        }
+    }
+
     private static final String DRL_INSERT_FACT = """
                                       package com.example.drools
                                       
@@ -142,6 +179,70 @@ public class FiringOrderTest extends BaseModelTest {
         ruleCActivatesBeforeRuleB(runType, DRL_UPDATE_FACT);
     }
 
+    private static final String DRL_AUTO_FOCUS_PREEMPTS = """
+                                      package com.example.drools
+
+                                      import %s.TestFact;
+
+                                      global java.util.List fired;
+
+                                      rule "Prepare source fact"
+                                          ruleflow-group "primaryGroup"
+                                      when
+                                          $source : TestFact(name == "source", 
state == "PENDING")
+                                      then
+                                          modify($source) { setState("READY") 
};
+                                      end
+
+                                      rule "Auto-focus target group"
+                                          ruleflow-group "autoFocusGroup"
+                                          auto-focus true
+                                      when
+                                          $source : TestFact(autoFocusTarget 
== false, state == "READY", priorityHandled == false)
+                                          $target : TestFact(autoFocusTarget 
== true, state == "PENDING", priorityHandled == false)
+                                      then
+                                          modify($source) {
+                                              setState("PENDING"),
+                                              setPriorityHandled(true)
+                                          };
+                                          modify($target) {
+                                              setState("READY"),
+                                              setPriorityHandled(true)
+                                          };
+                                          fired.add("auto-focus");
+                                      end
+
+                                      rule "Process ready fact"
+                                          ruleflow-group "primaryGroup"
+                                      when
+                                          $fact : TestFact(state == "READY")
+                                      then
+                                          modify($fact) { setState("COMPLETE") 
};
+                                          fired.add("process-" + 
$fact.getName());
+                                      end
+                                      
""".formatted(FiringOrderTest.class.getName());
+
+    @ParameterizedTest
+    @MethodSource("parameters")
+    void autoFocusedGroupPreemptsPreviouslyFocusedGroup(RUN_TYPE runType) {
+        final KieSession kieSession = getKieSession(runType, 
DRL_AUTO_FOCUS_PREEMPTS);
+
+        try {
+            final List<String> firedRules = new ArrayList<>();
+            kieSession.setGlobal("fired", firedRules);
+            kieSession.insert(new TestFact("source", false));
+            kieSession.insert(new TestFact("target", true));
+            kieSession.getAgenda().getAgendaGroup("primaryGroup").setFocus();
+
+            kieSession.fireAllRules();
+
+            assertThat(firedRules).as("Auto-focused group should preempt the 
previously focused group")
+                    .containsExactly("auto-focus", "process-target", 
"process-source");
+        } finally {
+            kieSession.dispose();
+        }
+    }
+
     void ruleCActivatesBeforeRuleB(RUN_TYPE runType, String drl) {
         final KieSession kieSession = getKieSession(runType, drl);
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to