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

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


The following commit(s) were added to refs/heads/main by this push:
     new 87b2f656c4 [KIE-1064] simplify session serialization by adding dormant 
activations to rule executor (#5821)
87b2f656c4 is described below

commit 87b2f656c495ef61c048db7cc3aedf2a0ed821bd
Author: Mario Fusco <[email protected]>
AuthorDate: Wed Apr 10 15:26:49 2024 +0200

    [KIE-1064] simplify session serialization by adding dormant activations to 
rule executor (#5821)
    
    * [KIE-1064] simplify session serialization by adding dormant activations 
to rule executor
    
    * wip
    
    * wip
    
    * wip
    
    * wip
    
    * wip
    
    * final rework
---
 .../org/drools/core/common/ActivationsManager.java |   2 +-
 .../drools/core/common/AgendaGroupsManager.java    |   8 +-
 .../org/drools/core/phreak/EagerPhreakBuilder.java |   5 +-
 .../org/drools/core/phreak/LazyPhreakBuilder.java  |   5 +-
 .../drools/core/phreak/PhreakAccumulateNode.java   |   5 +-
 .../org/drools/core/phreak/PhreakBranchNode.java   |  32 ++--
 .../drools/core/phreak/PhreakRuleTerminalNode.java |  83 +++++----
 .../java/org/drools/core/phreak/RuleExecutor.java  | 115 ++++++++----
 .../org/drools/core/reteoo/AlphaTerminalNode.java  |  14 +-
 .../drools/core/reteoo/ModifyPreviousTuples.java   |   2 +-
 .../org/drools/core/reteoo/RuleTerminalNode.java   |   4 +-
 .../core/reteoo/RuleTerminalNodeLeftTuple.java     |  15 +-
 .../java/org/drools/core/reteoo/TupleFactory.java  |  13 +-
 .../main/java/org/drools/core/util/LinkedList.java |  12 +-
 .../drools/kiesession/agenda/DefaultAgenda.java    |   2 +-
 .../dialect/mvel/MVELAccumulateBuilderTest.java    |  19 +-
 .../iterators/PhreakActivationIterator.java        | 198 ++-------------------
 .../serialization/protobuf/MarshallingTest.java    |  67 ++++---
 .../integrationtests/AbstractCepEspTest.java       |   2 +-
 .../integrationtests/ExecutionFlowControlTest.java |  12 +-
 .../integrationtests/NamedConsequencesTest.java    |   7 +-
 ...MaintenanceSystemRuleTerminalNodeLeftTuple.java |   2 +-
 22 files changed, 270 insertions(+), 354 deletions(-)

diff --git 
a/drools-core/src/main/java/org/drools/core/common/ActivationsManager.java 
b/drools-core/src/main/java/org/drools/core/common/ActivationsManager.java
index 5042d5fce5..2ad3ba7ae0 100644
--- a/drools-core/src/main/java/org/drools/core/common/ActivationsManager.java
+++ b/drools-core/src/main/java/org/drools/core/common/ActivationsManager.java
@@ -95,7 +95,7 @@ public interface ActivationsManager {
         if (!ruleAgendaItem.isQueued()) {
             
ruleAgendaItem.getRuleExecutor().getPathMemory().queueRuleAgendaItem(this);
         }
-        ruleAgendaItem.getRuleExecutor().addLeftTuple( justified.getTuple() );
+        
ruleAgendaItem.getRuleExecutor().modifyActiveTuple((RuleTerminalNodeLeftTuple) 
justified.getTuple() );
     }
 
     default ActivationsManager getPartitionedAgenda(int partitionNr) {
diff --git 
a/drools-core/src/main/java/org/drools/core/common/AgendaGroupsManager.java 
b/drools-core/src/main/java/org/drools/core/common/AgendaGroupsManager.java
index 84f5a354eb..fe6ab7aeca 100644
--- a/drools-core/src/main/java/org/drools/core/common/AgendaGroupsManager.java
+++ b/drools-core/src/main/java/org/drools/core/common/AgendaGroupsManager.java
@@ -218,8 +218,8 @@ public interface AgendaGroupsManager extends Externalizable 
{
             }
             int count = 0;
             for ( RuleAgendaItem item : mainAgendaGroup.getActivations() ) {
-                if (!(item.getRuleExecutor().getLeftTupleList().isEmpty())) {
-                    count = count + 
item.getRuleExecutor().getLeftTupleList().size();
+                if (!(item.getRuleExecutor().getActiveMatches().isEmpty())) {
+                    count = count + 
item.getRuleExecutor().getActiveMatches().size();
                 }
             }
             return count;
@@ -512,8 +512,8 @@ public interface AgendaGroupsManager extends Externalizable 
{
 
             int count = 0;
             for ( RuleAgendaItem item : group.getActivations() ) {
-                if (!item.getRuleExecutor().getLeftTupleList().isEmpty()) {
-                    count = count + 
item.getRuleExecutor().getLeftTupleList().size();
+                if (!item.getRuleExecutor().getActiveMatches().isEmpty()) {
+                    count = count + 
item.getRuleExecutor().getActiveMatches().size();
                 }
             }
             return count;
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java 
b/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java
index a4d37f49d3..2c4e58d806 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java
@@ -62,6 +62,7 @@ import org.drools.core.reteoo.PathMemory;
 import org.drools.core.reteoo.QueryElementNode;
 import org.drools.core.reteoo.RightInputAdapterNode;
 import org.drools.core.reteoo.RightTuple;
+import org.drools.core.reteoo.RuleTerminalNodeLeftTuple;
 import org.drools.core.reteoo.RuntimeComponentFactory;
 import org.drools.core.reteoo.SegmentMemory;
 import org.drools.core.reteoo.SegmentMemory.MemoryPrototype;
@@ -1245,7 +1246,7 @@ public class EagerPhreakBuilder implements PhreakBuilder {
                 TerminalNode rtn = ( TerminalNode ) node;
                 InternalAgenda agenda = wm.getAgenda();
                 RuleAgendaItem agendaItem = 
AlphaTerminalNode.getRuleAgendaItem( wm, agenda, rtn, insert );
-                PhreakRuleTerminalNode.doLeftTupleInsert( rtn, 
agendaItem.getRuleExecutor(), agenda, agendaItem, peer );
+                PhreakRuleTerminalNode.doLeftTupleInsert( rtn, 
agendaItem.getRuleExecutor(), agenda, agendaItem, (RuleTerminalNodeLeftTuple) 
peer );
             }
             return peer;
         }
@@ -1274,7 +1275,7 @@ public class EagerPhreakBuilder implements PhreakBuilder {
         if (NodeTypeEnums.isTerminalNode(lt.getSink())) {
             PathMemory pmem = (PathMemory) 
wm.getNodeMemories().peekNodeMemory( lt.getSink());
             if (pmem != null) {
-                PhreakRuleTerminalNode.doLeftDelete( 
pmem.getActualActivationsManager( wm ), 
pmem.getRuleAgendaItem().getRuleExecutor(), lt );
+                PhreakRuleTerminalNode.doLeftDelete( 
pmem.getActualActivationsManager( wm ), 
pmem.getRuleAgendaItem().getRuleExecutor(), (RuleTerminalNodeLeftTuple) lt );
             }
         } else {
             if (lt.getContextObject() instanceof AccumulateContext) {
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java 
b/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java
index 6402ba6eba..52e6b86fb8 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java
@@ -70,6 +70,7 @@ import org.drools.core.reteoo.QueryElementNode;
 import org.drools.core.reteoo.RightInputAdapterNode;
 import org.drools.core.reteoo.RightInputAdapterNode.RiaPathMemory;
 import org.drools.core.reteoo.RightTuple;
+import org.drools.core.reteoo.RuleTerminalNodeLeftTuple;
 import org.drools.core.reteoo.RuntimeComponentFactory;
 import org.drools.core.reteoo.SegmentMemory;
 import org.drools.core.reteoo.SegmentNodeMemory;
@@ -978,7 +979,7 @@ class LazyPhreakBuilder implements PhreakBuilder {
                 TerminalNode rtn = ( TerminalNode ) node;
                 InternalAgenda agenda = wm.getAgenda();
                 RuleAgendaItem agendaItem = 
AlphaTerminalNode.getRuleAgendaItem( wm, agenda, rtn, insert );
-                PhreakRuleTerminalNode.doLeftTupleInsert( rtn, 
agendaItem.getRuleExecutor(), agenda, agendaItem, peer );
+                PhreakRuleTerminalNode.doLeftTupleInsert( rtn, 
agendaItem.getRuleExecutor(), agenda, agendaItem, (RuleTerminalNodeLeftTuple) 
peer );
             }
             return peer;
         }
@@ -1007,7 +1008,7 @@ class LazyPhreakBuilder implements PhreakBuilder {
         if (NodeTypeEnums.isTerminalNode(lt.getSink())) {
             PathMemory pmem = (PathMemory) 
wm.getNodeMemories().peekNodeMemory( lt.getSink());
             if (pmem != null) {
-                PhreakRuleTerminalNode.doLeftDelete( 
pmem.getActualActivationsManager( wm ), 
pmem.getRuleAgendaItem().getRuleExecutor(), lt );
+                PhreakRuleTerminalNode.doLeftDelete( 
pmem.getActualActivationsManager( wm ), 
pmem.getRuleAgendaItem().getRuleExecutor(), (RuleTerminalNodeLeftTuple) lt );
             }
         } else {
             if (lt.getContextObject() instanceof AccumulateContext) {
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakAccumulateNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakAccumulateNode.java
index 33e72c91ec..e87a4fba13 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakAccumulateNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakAccumulateNode.java
@@ -249,8 +249,7 @@ public class PhreakAccumulateNode {
                 FastIterator leftIt = accNode.getLeftIterator( ltm );
 
                 for ( TupleImpl leftTuple = accNode.getFirstLeftTuple( 
rightTuple, ltm, leftIt ); leftTuple != null; leftTuple = (LeftTuple) 
leftIt.next( leftTuple ) ) {
-                    if ( constraints.isAllowedCachedRight(leftTuple, 
contextEntry
-                                                         ) ) {
+                    if ( constraints.isAllowedCachedRight(leftTuple, 
contextEntry) ) {
                         final BaseAccumulation accctx = (BaseAccumulation) 
leftTuple.getContextObject();
                         addMatch( accNode, accumulate, leftTuple, rightTuple,
                                   null, null, reteEvaluator, am,
@@ -717,7 +716,7 @@ public class PhreakAccumulateNode {
                           final boolean useLeftMemory,
                           final boolean leftPropagation) {
         TupleImpl tuple = leftTuple;
-        InternalFactHandle handle = (InternalFactHandle) 
rightTuple.getFactHandle();
+        InternalFactHandle handle = rightTuple.getFactHandle();
 
         if (accNode.isRightInputIsRiaNode()) {
             // if there is a subnetwork, handle must be unwrapped
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java 
b/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
index 18c2694df7..06b03f9752 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/PhreakBranchNode.java
@@ -18,15 +18,16 @@
  */
 package org.drools.core.phreak;
 
+import org.drools.base.reteoo.NodeTypeEnums;
 import org.drools.core.common.ActivationsManager;
 import org.drools.core.common.TupleSets;
 import org.drools.core.reteoo.ConditionalBranchEvaluator;
 import org.drools.core.reteoo.ConditionalBranchEvaluator.ConditionalExecution;
 import org.drools.core.reteoo.ConditionalBranchNode;
 import org.drools.core.reteoo.ConditionalBranchNode.ConditionalBranchMemory;
-import org.drools.core.reteoo.LeftTuple;
 import org.drools.core.reteoo.LeftTupleSink;
 import org.drools.core.reteoo.RuleTerminalNode;
+import org.drools.core.reteoo.RuleTerminalNodeLeftTuple;
 import org.drools.core.reteoo.TupleFactory;
 import org.drools.core.reteoo.TupleImpl;
 
@@ -67,8 +68,6 @@ public class PhreakBranchNode {
                               RuleExecutor executor) {
         ConditionalBranchEvaluator branchEvaluator = 
branchNode.getBranchEvaluator();
 
-        RuleAgendaItem ruleAgendaItem = executor.getRuleAgendaItem();
-
         for (TupleImpl leftTuple = srcLeftTuples.getInsertFirst(); leftTuple 
!= null; ) {
             TupleImpl next = leftTuple.getStagedNext();
 
@@ -79,7 +78,7 @@ public class PhreakBranchNode {
 
             if (conditionalExecution != null) {
                 RuleTerminalNode rtn = (RuleTerminalNode) 
conditionalExecution.getSink().getFirstLeftTupleSink();
-                TupleImpl branchedLeftTuple = 
TupleFactory.createLeftTuple(leftTuple,
+                RuleTerminalNodeLeftTuple branchedLeftTuple = 
(RuleTerminalNodeLeftTuple) TupleFactory.createLeftTuple(leftTuple,
                                                                            rtn,
                                                                            
leftTuple.getPropagationContext(), useLeftMemory);
                 PhreakRuleTerminalNode.doLeftTupleInsert( rtn, executor, 
activationsManager,
@@ -107,7 +106,6 @@ public class PhreakBranchNode {
                               TupleSets stagedLeftTuples,
                               RuleExecutor executor) {
         ConditionalBranchEvaluator branchEvaluator = 
branchNode.getBranchEvaluator();
-        RuleAgendaItem ruleAgendaItem = executor.getRuleAgendaItem();
 
         for (TupleImpl leftTuple = srcLeftTuples.getUpdateFirst(); leftTuple 
!= null; ) {
             TupleImpl next = leftTuple.getStagedNext();
@@ -134,7 +132,7 @@ public class PhreakBranchNode {
                 if (newRtn == null) {
                     // old exits, new does not, so delete
                     if ( branchTuples.rtnLeftTuple.getMemory() != null ) {
-                        executor.removeLeftTuple(branchTuples.rtnLeftTuple);
+                        executor.removeActiveTuple(branchTuples.rtnLeftTuple);
                     }
                     PhreakRuleTerminalNode.doLeftDelete(activationsManager, 
executor, branchTuples.rtnLeftTuple);
 
@@ -145,11 +143,11 @@ public class PhreakBranchNode {
                 } else {
                     // old and new on different branches, delete one and 
insert the other
                     if ( branchTuples.rtnLeftTuple.getMemory() != null ) {
-                        executor.removeLeftTuple(branchTuples.rtnLeftTuple);
+                        executor.removeActiveTuple(branchTuples.rtnLeftTuple);
                     }
                     PhreakRuleTerminalNode.doLeftDelete(activationsManager, 
executor, branchTuples.rtnLeftTuple);
 
-                    branchTuples.rtnLeftTuple = 
TupleFactory.createLeftTuple(leftTuple,
+                    branchTuples.rtnLeftTuple = (RuleTerminalNodeLeftTuple) 
TupleFactory.createLeftTuple(leftTuple,
                                                                              
newRtn,
                                                                              
leftTuple.getPropagationContext(), true);
                     PhreakRuleTerminalNode.doLeftTupleInsert( newRtn, 
executor, activationsManager,
@@ -158,7 +156,7 @@ public class PhreakBranchNode {
 
             } else if (newRtn != null) {
                 // old does not exist, new exists, so insert
-                branchTuples.rtnLeftTuple = 
TupleFactory.createLeftTuple(leftTuple, newRtn,
+                branchTuples.rtnLeftTuple = (RuleTerminalNodeLeftTuple) 
TupleFactory.createLeftTuple(leftTuple, newRtn,
                                                                          
leftTuple.getPropagationContext(), true);
                 PhreakRuleTerminalNode.doLeftTupleInsert( newRtn, executor, 
activationsManager,
                                                           
executor.getRuleAgendaItem(), branchTuples.rtnLeftTuple) ;
@@ -168,12 +166,12 @@ public class PhreakBranchNode {
             if (branchTuples.mainLeftTuple != null) {
                 normalizeStagedTuples( stagedLeftTuples, 
branchTuples.mainLeftTuple );
 
-                if (!breaking) {
-                    // child exist, new one does, so update
-                    trgLeftTuples.addUpdate(branchTuples.mainLeftTuple);
-                } else {
+                if (breaking && 
!NodeTypeEnums.isTerminalNode(branchTuples.mainLeftTuple.getSink())) {
                     // child exist, new one does not, so delete
                     trgLeftTuples.addDelete(branchTuples.mainLeftTuple);
+                } else {
+                    // child exist, new one does, so update
+                    trgLeftTuples.addUpdate(branchTuples.mainLeftTuple);
                 }
             } else if (!breaking) {
                 // child didn't exist, new one does, so insert
@@ -200,7 +198,7 @@ public class PhreakBranchNode {
 
             if (branchTuples.rtnLeftTuple != null) {
                 if ( branchTuples.rtnLeftTuple.getMemory() != null ) {
-                    executor.removeLeftTuple(branchTuples.rtnLeftTuple);
+                    executor.removeActiveTuple(branchTuples.rtnLeftTuple);
                 }
                 PhreakRuleTerminalNode.doLeftDelete(activationsManager, 
executor, branchTuples.rtnLeftTuple);
             }
@@ -230,14 +228,14 @@ public class PhreakBranchNode {
             if (child.getSink() == sink ) {
                 branchTuples.mainLeftTuple = child;
             } else {
-                branchTuples.rtnLeftTuple = child;
+                branchTuples.rtnLeftTuple = (RuleTerminalNodeLeftTuple) child;
             }
             child = child.getHandleNext();
             if ( child != null ) {
                 if (child.getSink() == sink ) {
                     branchTuples.mainLeftTuple = child;
                 } else {
-                    branchTuples.rtnLeftTuple = child;
+                    branchTuples.rtnLeftTuple = (RuleTerminalNodeLeftTuple) 
child;
                 }
             }
         }
@@ -245,7 +243,7 @@ public class PhreakBranchNode {
     }
 
     private static class BranchTuples {
-        TupleImpl rtnLeftTuple;
+        RuleTerminalNodeLeftTuple rtnLeftTuple;
         TupleImpl mainLeftTuple;
     }
 }
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 2ccd23ed47..707dccfcca 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
@@ -26,7 +26,6 @@ import org.drools.core.common.InternalFactHandle;
 import org.drools.core.common.PropagationContext;
 import org.drools.core.common.ReteEvaluator;
 import org.drools.core.common.TupleSets;
-import org.drools.core.reteoo.LeftTuple;
 import org.drools.core.reteoo.ObjectTypeConf;
 import org.drools.core.reteoo.RuleTerminalNode;
 import org.drools.core.reteoo.RuleTerminalNodeLeftTuple;
@@ -74,8 +73,8 @@ public class PhreakRuleTerminalNode {
             activationsManager.getAgendaGroupsManager().setFocus( 
ruleAgendaItem.getAgendaGroup() );
         }
 
-        for (TupleImpl leftTuple = srcLeftTuples.getInsertFirst(); leftTuple 
!= null; ) {
-            TupleImpl next = leftTuple.getStagedNext();
+        for (RuleTerminalNodeLeftTuple leftTuple = (RuleTerminalNodeLeftTuple) 
srcLeftTuples.getInsertFirst(); leftTuple != null; ) {
+            RuleTerminalNodeLeftTuple next = (RuleTerminalNodeLeftTuple) 
leftTuple.getStagedNext();
 
             doLeftTupleInsert(rtnNode, executor, activationsManager, 
ruleAgendaItem, leftTuple);
 
@@ -95,10 +94,10 @@ public class PhreakRuleTerminalNode {
     }
     public static void doLeftTupleInsert(TerminalNode rtnNode, RuleExecutor 
executor,
                                          ActivationsManager 
activationsManager, RuleAgendaItem ruleAgendaItem,
-                                         TupleImpl leftTuple) {
+                                         RuleTerminalNodeLeftTuple leftTuple) {
         ReteEvaluator reteEvaluator = activationsManager.getReteEvaluator();
         if ( reteEvaluator.getRuleSessionConfiguration().isDirectFiring() ) {
-            executor.addLeftTuple(leftTuple);
+            executor.addActiveTuple(leftTuple);
             return;
         }
 
@@ -112,32 +111,32 @@ public class PhreakRuleTerminalNode {
             pctx = leftTuple.getPropagationContext();
         }
 
-        int salienceInt = getSalienceValue(rtnNode, ruleAgendaItem, 
(InternalMatch) leftTuple, reteEvaluator);
+        int salienceInt = getSalienceValue(rtnNode, ruleAgendaItem, leftTuple, 
reteEvaluator);
 
-        RuleTerminalNodeLeftTuple rtnLeftTuple = (RuleTerminalNodeLeftTuple) 
leftTuple;
-        activationsManager.createAgendaItem( rtnLeftTuple, salienceInt, pctx, 
ruleAgendaItem, ruleAgendaItem.getAgendaGroup() );
+        activationsManager.createAgendaItem( leftTuple, salienceInt, pctx, 
ruleAgendaItem, ruleAgendaItem.getAgendaGroup() );
 
-        
activationsManager.getAgendaEventSupport().fireActivationCreated(rtnLeftTuple, 
activationsManager.getReteEvaluator());
+        
activationsManager.getAgendaEventSupport().fireActivationCreated(leftTuple, 
activationsManager.getReteEvaluator());
 
         if ( rtnNode.getRule().isLockOnActive() && pctx.getType() != 
PropagationContext.Type.RULE_ADDITION ) {
             pctx = leftTuple.findMostRecentPropagationContext();
             InternalAgendaGroup agendaGroup = 
executor.getRuleAgendaItem().getAgendaGroup();
             if (blockedByLockOnActive(rtnNode.getRule(), pctx, agendaGroup)) {
-                
activationsManager.getAgendaEventSupport().fireActivationCancelled(rtnLeftTuple,
 reteEvaluator, MatchCancelledCause.FILTER );
+                
activationsManager.getAgendaEventSupport().fireActivationCancelled(leftTuple, 
reteEvaluator, MatchCancelledCause.FILTER );
                 return;
             }
         }
 
-        if (activationsManager.getActivationsFilter() != null && 
!activationsManager.getActivationsFilter().accept( rtnLeftTuple )) {
-            // only relevant for seralization, to not refire Matches already 
fired
+        if (activationsManager.getActivationsFilter() != null && 
!activationsManager.getActivationsFilter().accept( leftTuple )) {
+            // only relevant for serialization, to not refire Matches already 
fired
+            executor.addDormantTuple(leftTuple );
             return;
         }
 
-        executor.addLeftTuple( leftTuple );
+        executor.addActiveTuple(leftTuple );
 
-        activationsManager.addItemToActivationGroup( rtnLeftTuple );
+        activationsManager.addItemToActivationGroup( leftTuple );
         if ( !rtnNode.isFireDirect() && executor.isDeclarativeAgendaEnabled() 
) {
-            insertAndStageActivation( reteEvaluator, rtnLeftTuple );
+            insertAndStageActivation( reteEvaluator, leftTuple );
         }
     }
 
@@ -164,8 +163,8 @@ public class PhreakRuleTerminalNode {
             
activationsManager.getAgendaGroupsManager().setFocus(ruleAgendaItem.getAgendaGroup());
         }
 
-        for (TupleImpl leftTuple = srcLeftTuples.getUpdateFirst(); leftTuple 
!= null; ) {
-            TupleImpl next = leftTuple.getStagedNext();
+        for (RuleTerminalNodeLeftTuple leftTuple = (RuleTerminalNodeLeftTuple) 
srcLeftTuples.getUpdateFirst(); leftTuple != null; ) {
+            RuleTerminalNodeLeftTuple next = (RuleTerminalNodeLeftTuple) 
leftTuple.getStagedNext();
 
             doLeftTupleUpdate(rtnNode, executor, activationsManager, 
leftTuple);
 
@@ -175,14 +174,13 @@ public class PhreakRuleTerminalNode {
     }
 
     public static void doLeftTupleUpdate(TerminalNode rtnNode, RuleExecutor 
executor,
-                                         ActivationsManager 
activationsManager, TupleImpl leftTuple) {
-        RuleTerminalNodeLeftTuple rtnLeftTuple = (RuleTerminalNodeLeftTuple) 
leftTuple;
+                                         ActivationsManager 
activationsManager, RuleTerminalNodeLeftTuple leftTuple) {
         ReteEvaluator reteEvaluator = activationsManager.getReteEvaluator();
 
         if ( reteEvaluator.getRuleSessionConfiguration().isDirectFiring() ) {
-            if (!rtnLeftTuple.isQueued() ) {
-                executor.addLeftTuple( leftTuple );
-                reteEvaluator.getRuleEventSupport().onUpdateMatch( 
rtnLeftTuple );
+            if (!leftTuple.isQueued() ) {
+                executor.modifyActiveTuple(leftTuple );
+                reteEvaluator.getRuleEventSupport().onUpdateMatch( leftTuple );
             }
             return;
         }
@@ -191,7 +189,7 @@ public class PhreakRuleTerminalNode {
 
         boolean blocked = false;
         if ( executor.isDeclarativeAgendaEnabled() ) {
-           if ( rtnLeftTuple.hasBlockers() ) {
+           if ( leftTuple.hasBlockers() ) {
                blocked = true; // declarativeAgenda still blocking LeftTuple, 
so don't add back ot list
            }
         } else {
@@ -203,10 +201,11 @@ public class PhreakRuleTerminalNode {
             }
         }
 
-        int salienceInt = getSalienceValue(rtnNode, 
executor.getRuleAgendaItem(), (InternalMatch) leftTuple, reteEvaluator);
+        int salienceInt = getSalienceValue(rtnNode, 
executor.getRuleAgendaItem(), leftTuple, reteEvaluator);
         
-        if (activationsManager.getActivationsFilter() != null && 
!activationsManager.getActivationsFilter().accept( rtnLeftTuple)) {
+        if (activationsManager.getActivationsFilter() != null && 
!activationsManager.getActivationsFilter().accept( leftTuple)) {
             // only relevant for serialization, to not re-fire Matches already 
fired
+            executor.addDormantTuple(leftTuple);
             return;
         }
         
@@ -220,23 +219,23 @@ public class PhreakRuleTerminalNode {
                 }
             }
             if ( addToExector ) {
-                if (!rtnLeftTuple.isQueued() ) {
+                if (!leftTuple.isQueued() ) {
                     // not queued, so already fired, so it's effectively 
recreated
-                    
activationsManager.getAgendaEventSupport().fireActivationCreated( rtnLeftTuple, 
reteEvaluator );
+                    
activationsManager.getAgendaEventSupport().fireActivationCreated( leftTuple, 
reteEvaluator );
 
-                    rtnLeftTuple.update( salienceInt, pctx );
-                    executor.addLeftTuple( leftTuple );
-                    reteEvaluator.getRuleEventSupport().onUpdateMatch( 
rtnLeftTuple );
+                    leftTuple.update( salienceInt, pctx );
+                    executor.modifyActiveTuple(leftTuple );
+                    reteEvaluator.getRuleEventSupport().onUpdateMatch( 
leftTuple );
                 }
             }
 
         } else {
             // LeftTuple is blocked, and thus not queued, so just update it's 
values
-            rtnLeftTuple.update(salienceInt, pctx);
+            leftTuple.update(salienceInt, pctx);
         }
 
         if( !rtnNode.isFireDirect() && executor.isDeclarativeAgendaEnabled()) {
-            modifyActivation(reteEvaluator, rtnLeftTuple);
+            modifyActivation(reteEvaluator, leftTuple);
         }
     }
 
@@ -255,30 +254,29 @@ public class PhreakRuleTerminalNode {
 
         for (TupleImpl leftTuple = srcLeftTuples.getDeleteFirst(); leftTuple 
!= null; ) {
             TupleImpl next = leftTuple.getStagedNext();
-            doLeftDelete(activationsManager, executor, leftTuple);
+            doLeftDelete(activationsManager, executor, 
(RuleTerminalNodeLeftTuple) leftTuple);
 
             leftTuple.clearStaged();
             leftTuple = next;
         }
     }
 
-    public static void doLeftDelete(ActivationsManager activationsManager, 
RuleExecutor executor, TupleImpl leftTuple) {
-        RuleTerminalNodeLeftTuple rtnLt = ( RuleTerminalNodeLeftTuple ) 
leftTuple;
-        rtnLt.setMatched( false );
+    public static void doLeftDelete(ActivationsManager activationsManager, 
RuleExecutor executor, RuleTerminalNodeLeftTuple leftTuple) {
+        leftTuple.setMatched( false );
 
-        rtnLt.cancelActivation( activationsManager );
+        leftTuple.cancelActivation( activationsManager );
 
         if ( leftTuple.getMemory() != null ) {
             // Expiration propagations should not be removed from the list, as 
they still need to fire
-            executor.removeLeftTuple(leftTuple);
+            executor.removeActiveTuple( leftTuple );
+        } else if ( leftTuple.getStagedType() == Tuple.DELETE && 
!leftTuple.isQueued() ) {
+            executor.removeDormantTuple( leftTuple );
         }
 
         leftTuple.setContextObject( null );
     }
 
-    private static boolean blockedByLockOnActive(RuleImpl rule,
-                                          PropagationContext pctx,
-                                          InternalAgendaGroup agendaGroup) {
+    private static boolean blockedByLockOnActive(RuleImpl rule, 
PropagationContext pctx, InternalAgendaGroup agendaGroup) {
         if ( rule.isLockOnActive() ) {
             long handleRecency = pctx.getFactHandle().getRecency();
             boolean isActive = agendaGroup.isActive();
@@ -288,9 +286,8 @@ public class PhreakRuleTerminalNode {
             if ( isActive && activatedForRecency < handleRecency &&
                  agendaGroup.getAutoFocusActivator() != pctx ) {
                 return true;
-            } else {
-                return clearedForRecency != -1 && clearedForRecency >= 
handleRecency;
             }
+            return clearedForRecency != -1 && clearedForRecency >= 
handleRecency;
 
         }
         return false;
diff --git a/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java 
b/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java
index 20d27d6885..675ba550e3 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/RuleExecutor.java
@@ -37,6 +37,7 @@ import org.drools.core.reteoo.Tuple;
 import org.drools.core.reteoo.TupleImpl;
 import org.drools.core.rule.consequence.InternalMatch;
 import org.drools.core.rule.consequence.KnowledgeHelper;
+import org.drools.core.util.LinkedList;
 import org.drools.core.util.Queue;
 import org.drools.core.util.QueueFactory;
 import org.drools.core.util.index.TupleList;
@@ -48,22 +49,26 @@ import org.slf4j.LoggerFactory;
 
 public class RuleExecutor {
 
+    private static final boolean DEBUG_DORMANT_TUPLE = false;
+
     protected static final Logger log = 
LoggerFactory.getLogger(RuleExecutor.class);
 
-    private final PathMemory           pmem;
-    private final RuleAgendaItem       ruleAgendaItem;
-    private final TupleList            tupleList;
+    private final PathMemory pmem;
+    private final RuleAgendaItem ruleAgendaItem;
+    private final TupleList activeMatches;
+    private final LinkedList<TupleImpl> dormantMatches;
     private final Queue<InternalMatch> queue;
-    private volatile boolean           dirty;
-    private final boolean              declarativeAgendaEnabled;
-    private boolean                    fireExitedEarly;
+    private volatile boolean dirty;
+    private final boolean declarativeAgendaEnabled;
+    private boolean fireExitedEarly;
 
     public RuleExecutor(final PathMemory pmem,
             RuleAgendaItem ruleAgendaItem,
             boolean declarativeAgendaEnabled) {
         this.pmem = pmem;
         this.ruleAgendaItem = ruleAgendaItem;
-        this.tupleList = new TupleList();
+        this.activeMatches = new TupleList();
+        this.dormantMatches = new LinkedList<>();
         this.declarativeAgendaEnabled = declarativeAgendaEnabled;
         this.queue = ruleAgendaItem.getRule().getSalience().isDynamic() ? 
QueueFactory.createQueue(MatchConflictResolver.INSTANCE) : null;
     }
@@ -89,15 +94,15 @@ public class RuleExecutor {
 
     private int doDirectFirings(ActivationsManager activationsManager, 
AgendaFilter filter, ReteEvaluator reteEvaluator) {
         RuleTerminalNode rtn = (RuleTerminalNode) pmem.getPathEndNode();
-        int directFirings = tupleList.size();
+        int directFirings = activeMatches.size();
 
-        for (TupleImpl tuple = tupleList.getFirst(); tuple != null; tuple = 
tupleList.getFirst()) {
+        for (RuleTerminalNodeLeftTuple tuple = (RuleTerminalNodeLeftTuple) 
activeMatches.getFirst(); tuple != null; tuple = (RuleTerminalNodeLeftTuple) 
activeMatches.getFirst()) {
             if (cancelAndContinue(reteEvaluator, rtn, tuple, filter)) {
                 directFirings--;
             } else {
-                fireActivationEvent(reteEvaluator, activationsManager, 
(InternalMatch) tuple, ((InternalMatch) tuple).getConsequence());
+                fireActivationEvent(reteEvaluator, activationsManager, tuple, 
tuple.getConsequence());
             }
-            removeLeftTuple( tuple );
+            removeActiveTuple(tuple );
         }
         ruleAgendaItem.remove();
         return directFirings;
@@ -114,7 +119,7 @@ public class RuleExecutor {
     private int fire( ReteEvaluator reteEvaluator, ActivationsManager 
activationsManager, AgendaFilter filter, int fireCount, int fireLimit) {
         int localFireCount = 0;
 
-        if (!tupleList.isEmpty()) {
+        if (!activeMatches.isEmpty()) {
             if (!fireExitedEarly && isDeclarativeAgendaEnabled()) {
                 // Network Evaluation can notify meta rules, which should be 
given a chance to fire first
                 RuleAgendaItem nextRule = activationsManager.peekNextRule();
@@ -187,17 +192,19 @@ public class RuleExecutor {
     }
 
     private TupleImpl getNextTuple() {
-        if (tupleList.isEmpty()) {
+        if (activeMatches.isEmpty()) {
             return null;
         }
         TupleImpl leftTuple;
         if (queue != null) {
             leftTuple = (TupleImpl) queue.dequeue();
-            tupleList.remove(leftTuple);
+            activeMatches.remove(leftTuple);
         } else {
-            leftTuple = tupleList.removeFirst();
+            leftTuple = activeMatches.removeFirst();
             ((InternalMatch) leftTuple).setQueued(false);
         }
+
+        addDormantTuple((RuleTerminalNodeLeftTuple) leftTuple);
         return leftTuple;
     }
 
@@ -206,7 +213,7 @@ public class RuleExecutor {
     }
 
     public void removeRuleAgendaItemWhenEmpty(ReteEvaluator reteEvaluator) {
-        if (!dirty && tupleList.isEmpty()) {
+        if (!dirty && activeMatches.isEmpty()) {
             if (log.isTraceEnabled()) {
                 log.trace("Removing RuleAgendaItem " + ruleAgendaItem);
             }
@@ -282,40 +289,81 @@ public class RuleExecutor {
         return RuleAgendaConflictResolver.doCompare(ruleAgendaItem, nextRule) 
>= 0;
     }
 
-    public TupleList getLeftTupleList() {
-        return tupleList;
+    public TupleList getActiveMatches() {
+        return activeMatches;
+    }
+
+    public LinkedList<TupleImpl> getDormantMatches() {
+        return dormantMatches;
     }
 
-    public void addLeftTuple(TupleImpl tuple) {
-        ((RuleTerminalNodeLeftTuple) tuple).setQueued(true);
-        this.tupleList.add(tuple);
+    public void addDormantTuple(RuleTerminalNodeLeftTuple tuple) {
+        if (DEBUG_DORMANT_TUPLE) {
+            if (tuple.isDormant()) {
+                throw new IllegalStateException();
+            }
+        }
+        dormantMatches.add(tuple);
+        if (DEBUG_DORMANT_TUPLE) {
+            tuple.setDormant(true);
+        }
+    }
+
+    public void removeDormantTuple(RuleTerminalNodeLeftTuple tuple) {
+        if (DEBUG_DORMANT_TUPLE) {
+            if (!tuple.isDormant()) {
+                throw new IllegalStateException();
+            }
+        }
+        dormantMatches.remove(tuple);
+        if (DEBUG_DORMANT_TUPLE) {
+            tuple.setDormant(false);
+        }
+   }
+
+    public void addActiveTuple(RuleTerminalNodeLeftTuple tuple) {
+        tuple.setQueued(true);
+        if (DEBUG_DORMANT_TUPLE) {
+            if (tuple.isDormant()) {
+                throw new IllegalStateException();
+            }
+        }
+        this.activeMatches.add(tuple);
         if (queue != null) {
             addQueuedLeftTuple(tuple);
         }
     }
 
-    public void addQueuedLeftTuple(Tuple tuple) {
-        int currentSalience = queue.isEmpty() ? 0 : queue.peek().getSalience();
-        queue.enqueue((InternalMatch) tuple);
-        updateSalience(currentSalience);
+    public void modifyActiveTuple(RuleTerminalNodeLeftTuple tuple) {
+        removeDormantTuple(tuple);
+        addActiveTuple(tuple);
     }
 
-    public void removeLeftTuple(TupleImpl tuple) {
-        ((RuleTerminalNodeLeftTuple) tuple).setQueued(false);
-        this.tupleList.remove(tuple);
+    public void removeActiveTuple(RuleTerminalNodeLeftTuple tuple) {
+        tuple.setQueued(false);
+        activeMatches.remove(tuple);
+        if (tuple.getStagedType() != Tuple.DELETE) {
+            addDormantTuple(tuple);
+        }
         if (queue != null) {
             removeQueuedLeftTuple(tuple);
         }
     }
 
-    private void removeQueuedLeftTuple(Tuple tuple) {
+    public void addQueuedLeftTuple(RuleTerminalNodeLeftTuple tuple) {
+        int currentSalience = queue.isEmpty() ? 0 : queue.peek().getSalience();
+        queue.enqueue(tuple);
+        updateSalience(currentSalience);
+    }
+
+    private void removeQueuedLeftTuple(RuleTerminalNodeLeftTuple tuple) {
         int currentSalience = queue.isEmpty() ? 0 : queue.peek().getSalience();
-        queue.dequeue(((InternalMatch) tuple));
+        queue.dequeue(tuple);
         updateSalience(currentSalience);
     }
 
     private void updateSalience(int currentSalience) {
-        // the queue may be emtpy if no more matches are left, so reset it to 
default salience 0
+        // the queue may be empty if no more matches are left, so reset it to 
default salience 0
         int newSalience = queue.isEmpty() ? 
SalienceInteger.DEFAULT_SALIENCE.getValue() : queue.peek().getSalience();
         if (currentSalience != newSalience) {
             // salience changed, so the RuleAgendaItem needs to be removed and 
re-added, for sorting
@@ -328,8 +376,8 @@ public class RuleExecutor {
     }
 
     public void cancel(ReteEvaluator reteEvaluator, EventSupport es) {
-        while (!tupleList.isEmpty()) {
-            RuleTerminalNodeLeftTuple rtnLt = (RuleTerminalNodeLeftTuple) 
tupleList.removeFirst();
+        while (!activeMatches.isEmpty()) {
+            RuleTerminalNodeLeftTuple rtnLt = (RuleTerminalNodeLeftTuple) 
activeMatches.removeFirst();
             if (queue != null) {
                 queue.dequeue(rtnLt);
             }
@@ -393,7 +441,6 @@ public class RuleExecutor {
             internalMatch.setActive(false);
             knowledgeHelper.reset();
         } catch ( final Exception e ) {
-            e.printStackTrace();
             
knowledgeHelper.restoreActivationOnConsequenceFailure(internalMatch);
             activationsManager.handleException(internalMatch, e);
         } finally {
diff --git 
a/drools-core/src/main/java/org/drools/core/reteoo/AlphaTerminalNode.java 
b/drools-core/src/main/java/org/drools/core/reteoo/AlphaTerminalNode.java
index a44c9b8294..66b53817c0 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/AlphaTerminalNode.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/AlphaTerminalNode.java
@@ -47,7 +47,7 @@ public class AlphaTerminalNode extends LeftInputAdapterNode {
         for (int i = 0; i < sinks.length; i++) {
             TerminalNode rtn = ( TerminalNode ) sinks[i];
             RuleAgendaItem agendaItem = getRuleAgendaItem( reteEvaluator, 
activationsManager, rtn, true );
-            TupleImpl leftTuple = TupleFactory.createLeftTuple(rtn, 
factHandle, true );
+            RuleTerminalNodeLeftTuple leftTuple = (RuleTerminalNodeLeftTuple) 
TupleFactory.createLeftTuple(rtn, factHandle, true );
             leftTuple.setPropagationContext( propagationContext );
 
             if ( rtn.getRule().getAutoFocus() && 
!agendaItem.getAgendaGroup().isActive() ) {
@@ -64,9 +64,9 @@ public class AlphaTerminalNode extends LeftInputAdapterNode {
         NetworkNode[] sinks = getSinks();
 
         for (int i = 0; i < sinks.length; i++) {
-            TerminalNode     rtn       = ( TerminalNode ) sinks[i];
-            ObjectTypeNodeId otnId     = rtn.getLeftInputOtnId();
-            TupleImpl        leftTuple = 
processDeletesFromModify(modifyPreviousTuples, context, reteEvaluator, otnId);
+            TerminalNode rtn = ( TerminalNode ) sinks[i];
+            ObjectTypeNodeId otnId = rtn.getLeftInputOtnId();
+            TupleImpl leftTuple = 
processDeletesFromModify(modifyPreviousTuples, context, reteEvaluator, otnId);
 
             RuleAgendaItem agendaItem = getRuleAgendaItem( reteEvaluator, 
activationsManager, rtn, true );
             RuleExecutor executor = agendaItem.getRuleExecutor();
@@ -76,7 +76,7 @@ public class AlphaTerminalNode extends LeftInputAdapterNode {
                 leftTuple.reAdd();
                 if ( context.getModificationMask().intersects( 
rtn.getLeftInferredMask() ) ) {
                     leftTuple.setPropagationContext( context );
-                    PhreakRuleTerminalNode.doLeftTupleUpdate( rtn, executor, 
activationsManager, leftTuple );
+                    PhreakRuleTerminalNode.doLeftTupleUpdate( rtn, executor, 
activationsManager, (RuleTerminalNodeLeftTuple) leftTuple );
                     if (leftTuple.isFullMatch()) {
                         ((InternalMatch) leftTuple).setActive(true);
                     }
@@ -85,7 +85,7 @@ public class AlphaTerminalNode extends LeftInputAdapterNode {
                 if ( context.getModificationMask().intersects( 
rtn.getLeftInferredMask() ) ) {
                     leftTuple = TupleFactory.createLeftTuple( rtn, factHandle, 
true );
                     leftTuple.setPropagationContext( context );
-                    PhreakRuleTerminalNode.doLeftTupleInsert( rtn, executor, 
activationsManager, agendaItem, leftTuple );
+                    PhreakRuleTerminalNode.doLeftTupleInsert( rtn, executor, 
activationsManager, agendaItem, (RuleTerminalNodeLeftTuple) leftTuple );
                 }
             }
         }
@@ -96,7 +96,7 @@ public class AlphaTerminalNode extends LeftInputAdapterNode {
         ActivationsManager activationsManager = 
reteEvaluator.getActivationsManager();
         leftTuple.setPropagationContext( context );
         TerminalNode rtn = (TerminalNode) leftTuple.getSink();
-        PhreakRuleTerminalNode.doLeftDelete( activationsManager, 
getRuleAgendaItem( reteEvaluator, activationsManager, rtn, false 
).getRuleExecutor(), leftTuple );
+        PhreakRuleTerminalNode.doLeftDelete( activationsManager, 
getRuleAgendaItem( reteEvaluator, activationsManager, rtn, false 
).getRuleExecutor(), (RuleTerminalNodeLeftTuple) leftTuple );
     }
 
     public static RuleAgendaItem getRuleAgendaItem(ReteEvaluator 
reteEvaluator, ActivationsManager activationsManager, TerminalNode rtn, boolean 
linkPmem ) {
diff --git 
a/drools-core/src/main/java/org/drools/core/reteoo/ModifyPreviousTuples.java 
b/drools-core/src/main/java/org/drools/core/reteoo/ModifyPreviousTuples.java
index 7dc61d80df..77b99649a4 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/ModifyPreviousTuples.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/ModifyPreviousTuples.java
@@ -81,7 +81,7 @@ public class ModifyPreviousTuples {
         } else {
             ActivationsManager activationsManager = 
reteEvaluator.getActivationsManager();
             PathMemory pathMemory = reteEvaluator.getNodeMemory( 
(TerminalNode) leftTuple.getSink() );
-            PhreakRuleTerminalNode.doLeftDelete(activationsManager, 
pathMemory.getRuleAgendaItem().getRuleExecutor(), leftTuple);
+            PhreakRuleTerminalNode.doLeftDelete(activationsManager, 
pathMemory.getRuleAgendaItem().getRuleExecutor(), (RuleTerminalNodeLeftTuple) 
leftTuple);
         }
     }
 
diff --git 
a/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java 
b/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java
index 9bb2559d67..097cd7aa94 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java
@@ -26,8 +26,6 @@ import org.drools.base.definitions.rule.impl.RuleImpl;
 import org.drools.base.reteoo.NodeTypeEnums;
 import org.drools.base.rule.Declaration;
 import org.drools.base.rule.GroupElement;
-import org.drools.core.common.InternalFactHandle;
-import org.drools.core.common.PropagationContext;
 import org.drools.core.common.ReteEvaluator;
 import org.drools.core.phreak.PhreakRuleTerminalNode;
 import org.drools.core.phreak.RuleExecutor;
@@ -144,7 +142,7 @@ public class RuleTerminalNode extends AbstractTerminalNode {
                 }
             }
             RuleExecutor ruleExecutor = 
((RuleTerminalNodeLeftTuple)leftTuple).getRuleAgendaItem().getRuleExecutor();
-            
PhreakRuleTerminalNode.doLeftDelete(ruleExecutor.getPathMemory().getActualActivationsManager(
 reteEvaluator ), ruleExecutor, leftTuple);
+            
PhreakRuleTerminalNode.doLeftDelete(ruleExecutor.getPathMemory().getActualActivationsManager(
 reteEvaluator ), ruleExecutor, (RuleTerminalNodeLeftTuple) leftTuple);
         }
     }
 
diff --git 
a/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNodeLeftTuple.java
 
b/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNodeLeftTuple.java
index c7a3da7192..b02f2afe6d 100644
--- 
a/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNodeLeftTuple.java
+++ 
b/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNodeLeftTuple.java
@@ -65,6 +65,9 @@ public class RuleTerminalNodeLeftTuple extends LeftTuple 
implements InternalMatc
     private RuleImpl rule;
     private Consequence consequence;
 
+    // left here for debugging purposes: switch 
RuleExecutor.DEBUG_DORMANT_TUPLE to true to enable this debugging
+    // private boolean dormant;
+
     public RuleTerminalNodeLeftTuple() {
         // constructor needed for serialisation
     }
@@ -221,7 +224,7 @@ public class RuleTerminalNodeLeftTuple extends LeftTuple 
implements InternalMatc
     }
 
     public void dequeue() {
-        ruleAgendaItem.getRuleExecutor().removeLeftTuple(this);
+        ruleAgendaItem.getRuleExecutor().removeActiveTuple(this);
     }
 
     public void remove() {
@@ -348,4 +351,14 @@ public class RuleTerminalNodeLeftTuple extends LeftTuple 
implements InternalMatc
     public boolean isFullMatch() {
         return true;
     }
+
+    public boolean isDormant() {
+        throw new IllegalStateException("This method can be called only for 
debugging purposes. Uncomment dormant boolean to enable debugging.");
+        // return dormant;
+    }
+
+    public void setDormant(boolean dormant) {
+        throw new IllegalStateException("This method can be called only for 
debugging purposes. Uncomment dormant boolean to enable debugging.");
+        // this.dormant = dormant;
+    }
 }
diff --git a/drools-core/src/main/java/org/drools/core/reteoo/TupleFactory.java 
b/drools-core/src/main/java/org/drools/core/reteoo/TupleFactory.java
index 777ed06c93..f0f9d7a1c6 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/TupleFactory.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/TupleFactory.java
@@ -19,14 +19,13 @@
 package org.drools.core.reteoo;
 
 import org.drools.base.reteoo.NodeTypeEnums;
-import org.drools.core.common.BaseNode;
 import org.drools.core.common.InternalFactHandle;
 import org.drools.core.common.PropagationContext;
 
 public class TupleFactory {
     public static TupleImpl createPeer(Sink n, TupleImpl original) {
         TupleImpl peer;
-        switch(((BaseNode)n).getType()) {
+        switch(n.getType()) {
             case NodeTypeEnums.JoinNode:
             case NodeTypeEnums.AccumulateNode:
             case NodeTypeEnums.QueryElementNode:
@@ -66,7 +65,7 @@ public class TupleFactory {
                                             final InternalFactHandle 
factHandle,
                                             boolean leftTupleMemoryEnabled) {
 
-        switch(((BaseNode)s).getType()) {
+        switch(s.getType()) {
             case NodeTypeEnums.JoinNode:
             case NodeTypeEnums.AccumulateNode:
             case NodeTypeEnums.QueryElementNode:
@@ -96,7 +95,7 @@ public class TupleFactory {
     public static TupleImpl createLeftTuple(final InternalFactHandle 
factHandle,
                                             final TupleImpl leftTuple,
                                             final Sink s) {
-        switch(((BaseNode)s).getType()) {
+        switch(s.getType()) {
             case NodeTypeEnums.JoinNode:
             case NodeTypeEnums.AccumulateNode:
             case NodeTypeEnums.QueryElementNode:
@@ -127,7 +126,7 @@ public class TupleFactory {
                                             Sink s,
                                             PropagationContext pctx,
                                             boolean leftTupleMemoryEnabled) {
-        switch(((BaseNode)s).getType()) {
+        switch(s.getType()) {
             case NodeTypeEnums.JoinNode:
             case NodeTypeEnums.AccumulateNode:
             case NodeTypeEnums.QueryElementNode:
@@ -157,7 +156,7 @@ public class TupleFactory {
     public static TupleImpl createLeftTuple(TupleImpl leftTuple,
                                             TupleImpl rightTuple,
                                             Sink s) {
-        switch(((BaseNode)s).getType()) {
+        switch(s.getType()) {
             case NodeTypeEnums.JoinNode:
             case NodeTypeEnums.AccumulateNode:
             case NodeTypeEnums.QueryElementNode:
@@ -190,7 +189,7 @@ public class TupleFactory {
                                             TupleImpl currentRightChild,
                                             Sink s,
                                             boolean leftTupleMemoryEnabled) {
-        switch(((BaseNode)s).getType()) {
+        switch(s.getType()) {
             case NodeTypeEnums.JoinNode:
             case NodeTypeEnums.AccumulateNode:
             case NodeTypeEnums.QueryElementNode:
diff --git a/drools-core/src/main/java/org/drools/core/util/LinkedList.java 
b/drools-core/src/main/java/org/drools/core/util/LinkedList.java
index b6b924ddf8..cc436849cf 100644
--- a/drools-core/src/main/java/org/drools/core/util/LinkedList.java
+++ b/drools-core/src/main/java/org/drools/core/util/LinkedList.java
@@ -22,12 +22,13 @@ import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
+import java.util.Collection;
 import java.util.NoSuchElementException;
 
 import org.drools.core.reteoo.TupleImpl;
 
 /**
- * This is a simple linked linked implementation. Each node must implement 
</code>LinkedListNode<code> so that it references
+ * This is a simple linked implementation. Each node must implement 
</code>LinkedListNode<code> so that it references
  * the node before and after it. This way a node can be removed without having 
to scan the list to find it. This class
  * does not provide an Iterator implementation as its designed for efficiency 
and not genericity. There are a number of
  * ways to iterate the list.
@@ -468,8 +469,7 @@ public class LinkedList<T extends DoubleLinkedEntry<T>>
         }
 
         public JavaUtilIterator(final LinkedList<T> list) {
-            this( list,
-                  true );
+            this( list, true );
         }
 
         public JavaUtilIterator(final LinkedList<T> list,
@@ -526,4 +526,10 @@ public class LinkedList<T extends DoubleLinkedEntry<T>>
         other.lastNode = lastNode;
         other.size = size;
     }
+
+    public <I> void addAllToCollection(Collection<I> c) {
+        for (T item = getFirst(); item != null; item = item.getNext()) {
+            c.add((I) item);
+        }
+    }
 }
diff --git 
a/drools-kiesession/src/main/java/org/drools/kiesession/agenda/DefaultAgenda.java
 
b/drools-kiesession/src/main/java/org/drools/kiesession/agenda/DefaultAgenda.java
index e74c10e80a..cd8978d309 100644
--- 
a/drools-kiesession/src/main/java/org/drools/kiesession/agenda/DefaultAgenda.java
+++ 
b/drools-kiesession/src/main/java/org/drools/kiesession/agenda/DefaultAgenda.java
@@ -284,7 +284,7 @@ public class DefaultAgenda implements InternalAgenda {
             // The lazy RuleAgendaItem must be fully evaluated, to see if 
there is a rule match
             RuleExecutor ruleExecutor = item.getRuleExecutor();
             ruleExecutor.evaluateNetwork(this);
-            TupleList list = ruleExecutor.getLeftTupleList();
+            TupleList list = ruleExecutor.getActiveMatches();
             for (RuleTerminalNodeLeftTuple lt = (RuleTerminalNodeLeftTuple) 
list.getFirst(); lt != null; lt = (RuleTerminalNodeLeftTuple) lt.getNext()) {
                 if ( ruleName.equals( lt.getRule().getName() ) && ( 
lt.checkProcessInstance( workingMemory, processInstanceId ) )) {
                     return true;
diff --git 
a/drools-mvel/src/test/java/org/drools/mvel/compiler/rule/builder/dialect/mvel/MVELAccumulateBuilderTest.java
 
b/drools-mvel/src/test/java/org/drools/mvel/compiler/rule/builder/dialect/mvel/MVELAccumulateBuilderTest.java
index 90bf0047b8..5aefec89e3 100644
--- 
a/drools-mvel/src/test/java/org/drools/mvel/compiler/rule/builder/dialect/mvel/MVELAccumulateBuilderTest.java
+++ 
b/drools-mvel/src/test/java/org/drools/mvel/compiler/rule/builder/dialect/mvel/MVELAccumulateBuilderTest.java
@@ -20,25 +20,24 @@ package org.drools.mvel.compiler.rule.builder.dialect.mvel;
 
 import java.util.Collections;
 
+import org.drools.base.definitions.InternalKnowledgePackage;
+import org.drools.base.reteoo.InitialFactImpl;
+import org.drools.base.rule.Accumulate;
 import org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl;
 import org.drools.compiler.builder.impl.KnowledgeBuilderImpl;
 import org.drools.compiler.compiler.DialectCompiletimeRegistry;
-import org.drools.core.reteoo.LeftTuple;
-import org.drools.drl.ast.descr.AccumulateDescr;
-import org.drools.drl.ast.descr.PackageDescr;
-import org.drools.drl.ast.descr.PatternDescr;
-import org.drools.drl.ast.descr.RuleDescr;
 import org.drools.compiler.rule.builder.RuleBuildContext;
 import org.drools.core.common.InternalFactHandle;
-import org.drools.base.definitions.InternalKnowledgePackage;
-import org.drools.kiesession.rulebase.InternalKnowledgeBase;
 import org.drools.core.reteoo.AccumulateNode;
-import org.drools.base.reteoo.InitialFactImpl;
 import org.drools.core.reteoo.LeftTuple;
 import org.drools.core.reteoo.MockLeftTupleSink;
 import org.drools.core.reteoo.MockTupleSource;
 import org.drools.core.reteoo.builder.BuildContext;
-import org.drools.base.rule.Accumulate;
+import org.drools.drl.ast.descr.AccumulateDescr;
+import org.drools.drl.ast.descr.PackageDescr;
+import org.drools.drl.ast.descr.PatternDescr;
+import org.drools.drl.ast.descr.RuleDescr;
+import org.drools.kiesession.rulebase.InternalKnowledgeBase;
 import org.drools.kiesession.rulebase.KnowledgeBaseFactory;
 import org.drools.kiesession.session.StatefulKnowledgeSessionImpl;
 import org.drools.mvel.MVELDialectRuntimeData;
@@ -98,7 +97,7 @@ public class MVELAccumulateBuilderTest {
                                             10 );
         final Cheese cheddar2 = new Cheese( "cheddar",
                                             8 );
-        final InternalFactHandle f0 = (InternalFactHandle) ksession.insert( 
new InitialFactImpl() );
+        final InternalFactHandle f0 = (InternalFactHandle) ksession.insert( 
InitialFactImpl.getInstance() );
         final InternalFactHandle f1 = (InternalFactHandle) ksession.insert( 
cheddar1 );
         final InternalFactHandle f2 = (InternalFactHandle) ksession.insert( 
cheddar2 );
         final LeftTuple tuple = new LeftTuple( f0,
diff --git 
a/drools-serialization-protobuf/src/main/java/org/drools/serialization/protobuf/iterators/PhreakActivationIterator.java
 
b/drools-serialization-protobuf/src/main/java/org/drools/serialization/protobuf/iterators/PhreakActivationIterator.java
index b12da2c012..8af734daaa 100644
--- 
a/drools-serialization-protobuf/src/main/java/org/drools/serialization/protobuf/iterators/PhreakActivationIterator.java
+++ 
b/drools-serialization-protobuf/src/main/java/org/drools/serialization/protobuf/iterators/PhreakActivationIterator.java
@@ -19,55 +19,23 @@
 package org.drools.serialization.protobuf.iterators;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 import org.drools.base.reteoo.NodeTypeEnums;
-import org.drools.core.common.InternalFactHandle;
-import org.drools.core.common.InternalWorkingMemory;
-import org.drools.core.common.Memory;
 import org.drools.core.common.ReteEvaluator;
 import org.drools.core.impl.InternalRuleBase;
-import org.drools.core.reteoo.AccumulateNode.AccumulateContext;
-import org.drools.core.reteoo.AccumulateNode.AccumulateMemory;
-import org.drools.core.reteoo.BetaMemory;
-import org.drools.core.reteoo.BetaNode;
-import org.drools.core.reteoo.FromNode.FromMemory;
-import org.drools.core.reteoo.LeftInputAdapterNode;
-import org.drools.core.reteoo.LeftTuple;
-import org.drools.core.reteoo.LeftTupleSink;
-import org.drools.core.reteoo.LeftTupleSource;
-import org.drools.core.reteoo.ObjectSource;
-import org.drools.core.reteoo.ObjectTypeNode;
-import org.drools.core.reteoo.RightTuple;
-import org.drools.core.reteoo.RuleTerminalNode;
+import org.drools.core.phreak.RuleExecutor;
+import org.drools.core.reteoo.PathMemory;
 import org.drools.core.reteoo.TerminalNode;
-import org.drools.core.reteoo.Tuple;
-import org.drools.core.reteoo.TupleImpl;
-import org.drools.core.reteoo.TupleMemory;
 import org.drools.core.rule.consequence.InternalMatch;
-import org.drools.core.util.FastIterator;
 import org.drools.core.util.Iterator;
 
-public class PhreakActivationIterator
-    implements
-    Iterator<InternalMatch> {
+public class PhreakActivationIterator implements Iterator<InternalMatch> {
 
-    private java.util.Iterator<InternalMatch> agendaItemIter;
-
-    List<InternalMatch> internalMatches;
-
-    PhreakActivationIterator() {
+    private final java.util.Iterator<InternalMatch> agendaItemIter;
 
-    }
-
-    private PhreakActivationIterator(ReteEvaluator reteEvaluator,
-                                     InternalRuleBase kbase) {
-        internalMatches = collectAgendaItems(kbase, reteEvaluator);
-        agendaItemIter =  internalMatches.iterator();
+    private PhreakActivationIterator(ReteEvaluator reteEvaluator, 
InternalRuleBase kbase) {
+        agendaItemIter =  collectAgendaItems(kbase, reteEvaluator).iterator();
     }
 
     public static PhreakActivationIterator iterator(ReteEvaluator 
reteEvaluator) {
@@ -82,158 +50,22 @@ public class PhreakActivationIterator
         }
     }
 
-    public static List<RuleTerminalNode> 
populateRuleTerminalNodes(InternalRuleBase kbase, Set<RuleTerminalNode>  
nodeSet) {
-        Collection<TerminalNode[]> nodesWithArray = 
kbase.getReteooBuilder().getTerminalNodes().values();
+    private static List<InternalMatch> collectAgendaItems(InternalRuleBase 
kbase, ReteEvaluator reteEvaluator) {
+        List<InternalMatch> internalMatches = new ArrayList<>();
 
-        for (TerminalNode[] nodeArray : nodesWithArray) {
+        for (TerminalNode[] nodeArray : 
kbase.getReteooBuilder().getTerminalNodes().values()) {
             for (TerminalNode node : nodeArray) {
                 if (node.getType() == NodeTypeEnums.RuleTerminalNode) {
-                    nodeSet.add((RuleTerminalNode) node);
-                }
-            }
-        }
-
-        return Arrays.asList(nodeSet.toArray(new 
RuleTerminalNode[nodeSet.size()]));
-    }
-
-    public static List<InternalMatch> collectAgendaItems(InternalRuleBase 
kbase, ReteEvaluator reteEvaluator) {
-        Set<RuleTerminalNode> nodeSet = new HashSet<>();
-        List<RuleTerminalNode> nodeList = populateRuleTerminalNodes(kbase, 
nodeSet);
-
-        List<InternalMatch> internalMatches = new ArrayList<>();
-        for ( RuleTerminalNode rtn : nodeList ) {
-            if ( !nodeSet.contains(rtn) ) {
-                // this node has already been processed
-                continue;
-            }
-            processLeftTuples(rtn.getLeftTupleSource(), internalMatches, 
nodeSet, reteEvaluator);
-        }
-        return internalMatches;
-    }
-
-    public static void processLeftTuples(LeftTupleSource node, 
List<InternalMatch> internalMatches, Set<RuleTerminalNode> nodeSet, 
ReteEvaluator reteEvaluator) {
-        LeftTupleSource node1 = node;
-        while (!NodeTypeEnums.isLeftInputAdapterNode((node1))) {
-            node1 = node1.getLeftTupleSource();
-        }
-        int maxShareCount = node1.getAssociationsSize();
-
-        while (!NodeTypeEnums.isLeftInputAdapterNode(node)) {
-            Memory memory = 
reteEvaluator.getNodeMemories().peekNodeMemory(node);
-            if (memory == null || memory.getSegmentMemory() == null) {
-                // segment has never been initialized, which means the rule 
has never been linked.
-                return;
-            }
-            if ( node.getAssociationsSize() == maxShareCount ) {
-                // the recurse must start from the first split node, otherwise 
we get partial overlaps in propagations
-                if (NodeTypeEnums.isBetaNode(node)) {
-                    BetaMemory bm;
-                    if (NodeTypeEnums.AccumulateNode == node.getType()) {
-                        AccumulateMemory am = (AccumulateMemory) memory;
-                        bm = am.getBetaMemory();
-                        FastIterator it = 
bm.getLeftTupleMemory().fullFastIterator();
-                        Tuple lt = BetaNode.getFirstTuple( 
bm.getLeftTupleMemory(), it );
-                        for (; lt != null; lt = (TupleImpl) it.next(lt)) {
-                            AccumulateContext accctx = (AccumulateContext) 
lt.getContextObject();
-                            collectFromPeers((TupleImpl) 
accctx.getResultLeftTuple(), internalMatches, nodeSet, reteEvaluator);
-                        }
-                    } else if ( NodeTypeEnums.ExistsNode == node.getType() ) {
-                        bm = (BetaMemory) 
reteEvaluator.getNodeMemories().peekNodeMemory(node);
-                        if (bm != null) {
-                            bm = (BetaMemory) 
reteEvaluator.getNodeMemories().peekNodeMemory(node);
-                            FastIterator it = 
bm.getRightTupleMemory().fullFastIterator(); // done off the RightTupleMemory, 
as exists only have unblocked tuples on the left side
-                            RightTuple   rt = (RightTuple) 
BetaNode.getFirstTuple(bm.getRightTupleMemory(), it);
-                            for (; rt != null; rt = (RightTuple) it.next(rt)) {
-                                for (LeftTuple lt = rt.getBlocked(); lt != 
null; lt = lt.getBlockedNext()) {
-                                    if (lt.getFirstChild() != null) {
-                                        collectFromPeers(lt.getFirstChild(), 
internalMatches, nodeSet, reteEvaluator);
-                                    }
-                                }
-                            }
-                        }
-                    } else {
-                        bm = (BetaMemory) 
reteEvaluator.getNodeMemories().peekNodeMemory(node);
-                        if (bm != null) {
-                            FastIterator it = 
bm.getLeftTupleMemory().fullFastIterator();
-                            Tuple lt = 
BetaNode.getFirstTuple(bm.getLeftTupleMemory(), it);
-                            for (; lt != null; lt = (TupleImpl) it.next(lt)) {
-                                if (lt.getFirstChild() != null) {
-                                    collectFromLeftInput(lt.getFirstChild(), 
internalMatches, nodeSet, reteEvaluator);
-                                }
-                            }
-                        }
-                    }
-                    return;
-                } else if (NodeTypeEnums.FromNode == node.getType()) {
-                    FromMemory fm = (FromMemory) 
reteEvaluator.getNodeMemories().peekNodeMemory(node);
-                    if (fm != null) {
-                        TupleMemory ltm = 
fm.getBetaMemory().getLeftTupleMemory();
-                        FastIterator it = ltm.fullFastIterator();
-                        for (TupleImpl lt = (TupleImpl) ltm.getFirst(null); lt 
!= null; lt = (TupleImpl) it.next(lt)) {
-                            if (lt.getFirstChild() != null) {
-                                collectFromLeftInput(lt.getFirstChild(), 
internalMatches, nodeSet, reteEvaluator);
-                            }
-                        }
+                    PathMemory pathMemory = (PathMemory) 
reteEvaluator.getNodeMemories().peekNodeMemory(node);
+                    if (pathMemory != null && pathMemory.getRuleAgendaItem() 
!= null) {
+                        RuleExecutor ruleExecutor = 
pathMemory.getRuleAgendaItem().getRuleExecutor();
+                        
ruleExecutor.getDormantMatches().addAllToCollection(internalMatches);
+                        
ruleExecutor.getActiveMatches().addAllToCollection(internalMatches);
                     }
-                    return;
                 }
             }
-            node = node.getLeftTupleSource();
-        }
-
-        // No beta or from nodes, so must retrieve LeftTuples from the LiaNode.
-        // This is done by scanning all the LeftTuples referenced from the 
FactHandles in the ObjectTypeNode
-        LeftInputAdapterNode lian = (LeftInputAdapterNode) node;
-        if ( !lian.isTerminal() ) {
-            Memory memory = 
reteEvaluator.getNodeMemories().peekNodeMemory(node);
-            if (memory == null || memory.getSegmentMemory() == null) {
-                // segment has never been initialized, which means the rule 
has never been linked.
-                return;
-            }
-        }
-
-        ObjectSource os = lian.getObjectSource();
-        while (os.getType() != NodeTypeEnums.ObjectTypeNode) {
-            os = os.getParentObjectSource();
-        }
-        ObjectTypeNode otn = (ObjectTypeNode) os;
-        LeftTupleSink firstLiaSink = 
lian.getSinkPropagator().getFirstLeftTupleSink();
-
-        java.util.Iterator<InternalFactHandle> it = 
otn.getFactHandlesIterator((InternalWorkingMemory) reteEvaluator);
-        while (it.hasNext()) {
-            InternalFactHandle fh = it.next();
-            fh.forEachLeftTuple( lt -> {
-                if (lt.getSink() == firstLiaSink ) {
-                    collectFromLeftInput(lt, internalMatches, nodeSet, 
reteEvaluator);
-                }
-            });
         }
-    }
 
-    private static void collectFromLeftInput(TupleImpl lt, List<InternalMatch> 
internalMatches, Set<RuleTerminalNode> nodeSet, ReteEvaluator reteEvaluator) {
-        for (; lt != null; lt = lt.getHandleNext()) {
-            collectFromPeers(lt, internalMatches, nodeSet, reteEvaluator);
-        }
-    }
-
-    private static void collectFromPeers(TupleImpl peer, List<InternalMatch> 
internalMatches, Set<RuleTerminalNode> nodeSet, ReteEvaluator reteEvaluator) {
-        while (peer != null) {
-            if (peer.getSink().getType() == NodeTypeEnums.AccumulateNode ) {
-                Object accctx = peer.getContextObject();
-                if (accctx instanceof AccumulateContext) {
-                    // lefttuple representing an accumulated value now have 
that value as context object (it was null before) and must be skipped here
-                    collectFromLeftInput((TupleImpl) ((AccumulateContext) 
accctx).getResultLeftTuple(), internalMatches, nodeSet, reteEvaluator);
-                }
-            } else if ( peer.getFirstChild() != null ) {
-                for (TupleImpl childLt = peer.getFirstChild(); childLt != 
null; childLt = childLt.getHandleNext()) {
-                    collectFromPeers(childLt, internalMatches, nodeSet, 
reteEvaluator);
-                }
-            } else if (peer.getSink().getType() == 
NodeTypeEnums.RuleTerminalNode ) {
-                internalMatches.add((InternalMatch) peer);
-                nodeSet.remove(peer.getSink()); // remove this 
RuleTerminalNode, as we know we've visited it already
-            }
-            peer = peer.getPeer();
-        }
+        return internalMatches;
     }
-
 }
diff --git 
a/drools-serialization-protobuf/src/test/java/org/drools/serialization/protobuf/MarshallingTest.java
 
b/drools-serialization-protobuf/src/test/java/org/drools/serialization/protobuf/MarshallingTest.java
index 9587944533..3258b90b1f 100644
--- 
a/drools-serialization-protobuf/src/test/java/org/drools/serialization/protobuf/MarshallingTest.java
+++ 
b/drools-serialization-protobuf/src/test/java/org/drools/serialization/protobuf/MarshallingTest.java
@@ -18,15 +18,38 @@
  */
 package org.drools.serialization.protobuf;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import org.drools.base.base.ClassObjectType;
 import org.drools.base.base.ValueResolver;
 import org.drools.base.common.DroolsObjectInputStream;
 import org.drools.base.common.DroolsObjectOutputStream;
-import org.drools.core.ClockType;
-import org.drools.core.SessionConfiguration;
-import org.drools.base.base.ClassObjectType;
-import org.drools.core.common.*;
 import org.drools.base.definitions.InternalKnowledgePackage;
 import org.drools.base.definitions.rule.impl.RuleImpl;
+import org.drools.base.rule.MapBackedClassLoader;
+import org.drools.base.rule.consequence.Consequence;
+import org.drools.base.rule.consequence.ConsequenceContext;
+import org.drools.core.ClockType;
+import org.drools.core.SessionConfiguration;
+import org.drools.core.common.BaseNode;
+import org.drools.core.common.InternalAgenda;
+import org.drools.core.common.InternalFactHandle;
+import org.drools.core.common.InternalWorkingMemory;
 import org.drools.core.impl.EnvironmentFactory;
 import org.drools.core.impl.RuleBaseFactory;
 import org.drools.core.marshalling.ClassObjectMarshallingStrategyAcceptor;
@@ -35,9 +58,6 @@ import org.drools.core.reteoo.MockTupleSource;
 import org.drools.core.reteoo.ObjectTypeNode;
 import org.drools.core.reteoo.RuleTerminalNode;
 import org.drools.core.reteoo.builder.BuildContext;
-import org.drools.base.rule.MapBackedClassLoader;
-import org.drools.base.rule.consequence.Consequence;
-import org.drools.base.rule.consequence.ConsequenceContext;
 import org.drools.core.time.impl.DurationTimer;
 import org.drools.core.time.impl.PseudoClockScheduler;
 import org.drools.core.util.KeyStoreConstants;
@@ -45,7 +65,15 @@ import org.drools.core.util.KeyStoreHelper;
 import org.drools.kiesession.rulebase.InternalKnowledgeBase;
 import org.drools.kiesession.rulebase.KnowledgeBaseFactory;
 import org.drools.mvel.CommonTestMethodBase;
-import org.drools.mvel.compiler.*;
+import org.drools.mvel.compiler.Address;
+import org.drools.mvel.compiler.Cell;
+import org.drools.mvel.compiler.Cheese;
+import org.drools.mvel.compiler.FactA;
+import org.drools.mvel.compiler.FactB;
+import org.drools.mvel.compiler.FactC;
+import org.drools.mvel.compiler.Message;
+import org.drools.mvel.compiler.Person;
+import org.drools.mvel.compiler.Primitives;
 import org.drools.mvel.integrationtests.IteratorToList;
 import 
org.drools.serialization.protobuf.marshalling.IdentityPlaceholderResolverStrategy;
 import org.drools.serialization.protobuf.marshalling.RuleBaseNodes;
@@ -63,7 +91,11 @@ import org.kie.api.marshalling.KieMarshallers;
 import org.kie.api.marshalling.Marshaller;
 import org.kie.api.marshalling.ObjectMarshallingStrategy;
 import org.kie.api.marshalling.ObjectMarshallingStrategyAcceptor;
-import org.kie.api.runtime.*;
+import org.kie.api.runtime.Environment;
+import org.kie.api.runtime.EnvironmentName;
+import org.kie.api.runtime.Globals;
+import org.kie.api.runtime.KieSession;
+import org.kie.api.runtime.KieSessionConfiguration;
 import org.kie.api.runtime.conf.ClockTypeOption;
 import org.kie.api.runtime.conf.TimedRuleExecutionOption;
 import org.kie.api.runtime.conf.TimerJobFactoryOption;
@@ -74,14 +106,6 @@ import org.kie.internal.builder.KnowledgeBuilderFactory;
 import org.kie.internal.marshalling.MarshallerFactory;
 import org.kie.internal.utils.KieHelper;
 
-import java.io.*;
-import java.net.URL;
-import java.util.*;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.fail;
 import static 
org.drools.serialization.protobuf.SerializationHelper.getSerialisedStatefulKnowledgeSession;
@@ -1491,20 +1515,17 @@ public class MarshallingTest extends 
CommonTestMethodBase {
         ksession.fireAllRules();
         assertThat(list.size()).isEqualTo(1);
 
-        ksession = getSerialisedStatefulKnowledgeSession( ksession,
-                                                          true );
+        ksession = getSerialisedStatefulKnowledgeSession( ksession, true );
 
         ksession.fireAllRules();
         assertThat(list.size()).isEqualTo(2);
 
-        ksession = getSerialisedStatefulKnowledgeSession( ksession,
-                                                          true );
+        ksession = getSerialisedStatefulKnowledgeSession( ksession, true );
         ksession.fireAllRules();
         assertThat(list.size()).isEqualTo(3);
 
         // should not grow any further
-        ksession = getSerialisedStatefulKnowledgeSession( ksession,
-                                                          true );
+        ksession = getSerialisedStatefulKnowledgeSession( ksession, true );
         ksession.fireAllRules();
         assertThat(list.size()).isEqualTo(3);
     }
diff --git 
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/AbstractCepEspTest.java
 
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/AbstractCepEspTest.java
index c3a308c772..0c16e17ee9 100644
--- 
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/AbstractCepEspTest.java
+++ 
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/AbstractCepEspTest.java
@@ -91,7 +91,7 @@ public abstract class AbstractCepEspTest {
         }
     }
 
-    @Test
+    @Test(timeout = 10000L)
     public void testDuplicateFiring2() {
 
         final String drl = "package org.test;\n" +
diff --git 
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/ExecutionFlowControlTest.java
 
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/ExecutionFlowControlTest.java
index 510bffa593..ebbd2d9f35 100644
--- 
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/ExecutionFlowControlTest.java
+++ 
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/ExecutionFlowControlTest.java
@@ -475,31 +475,31 @@ public class ExecutionFlowControlTest {
         assertThat(group1.size()).isEqualTo(1);
         RuleAgendaItem ruleItem1 = group1.getActivations().iterator().next();
         ruleItem1.getRuleExecutor().evaluateNetwork(wm.getAgenda());
-        
assertThat(ruleItem1.getRuleExecutor().getLeftTupleList().size()).isEqualTo(3);
+        
assertThat(ruleItem1.getRuleExecutor().getActiveMatches().size()).isEqualTo(3);
 
         ruleItem1.getRuleExecutor().fire(agenda);
         assertThat(group1.size()).isEqualTo(1);
-        
assertThat(ruleItem1.getRuleExecutor().getLeftTupleList().size()).isEqualTo(2);
+        
assertThat(ruleItem1.getRuleExecutor().getActiveMatches().size()).isEqualTo(2);
 
         ksession.update( brieHandle, brie );
         assertThat(group1.size()).isEqualTo(1);
         ruleItem1.getRuleExecutor().evaluateNetwork(wm.getAgenda());
-        
assertThat(ruleItem1.getRuleExecutor().getLeftTupleList().size()).isEqualTo(2);
+        
assertThat(ruleItem1.getRuleExecutor().getActiveMatches().size()).isEqualTo(2);
 
         InternalAgendaGroup group2 = 
agenda.getAgendaGroupsManager().getAgendaGroup( "group2" );
         agenda.getAgendaGroupsManager().setFocus( group2);
         assertThat(group2.size()).isEqualTo(1);
         RuleAgendaItem ruleItem2 = group2.getActivations().iterator().next();
         ruleItem2.getRuleExecutor().evaluateNetwork(wm.getAgenda());
-        
assertThat(ruleItem2.getRuleExecutor().getLeftTupleList().size()).isEqualTo(3);
+        
assertThat(ruleItem2.getRuleExecutor().getActiveMatches().size()).isEqualTo(3);
 
         ruleItem2.getRuleExecutor().fire(agenda);
         assertThat(group2.size()).isEqualTo(1);
-        
assertThat(ruleItem2.getRuleExecutor().getLeftTupleList().size()).isEqualTo(2);
+        
assertThat(ruleItem2.getRuleExecutor().getActiveMatches().size()).isEqualTo(2);
 
         ksession.update( brieHandle, brie );
         assertThat(group2.size()).isEqualTo(1);
-        
assertThat(ruleItem2.getRuleExecutor().getLeftTupleList().size()).isEqualTo(2);
+        
assertThat(ruleItem2.getRuleExecutor().getActiveMatches().size()).isEqualTo(2);
     }
 
     @Test
diff --git 
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/NamedConsequencesTest.java
 
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/NamedConsequencesTest.java
index f9e77b371c..3e700bb004 100644
--- 
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/NamedConsequencesTest.java
+++ 
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/mvel/integrationtests/NamedConsequencesTest.java
@@ -758,7 +758,7 @@ public class NamedConsequencesTest {
         KieBase kbase = KieBaseUtil.getKieBaseFromKieModuleFromDrl("test", 
kieBaseTestConfiguration, str);
         KieSession ksession = kbase.newKieSession();
 
-        List<String> results = new ArrayList<String>();
+        List<String> results = new ArrayList<>();
         ksession.setGlobal("results", results);
         for (int i = 1; i < 7; i++) {
             ksession.insert(new Fact(i));
@@ -788,6 +788,11 @@ public class NamedConsequencesTest {
         public void setStatus(Status status) {
             this.status = status;
         }
+
+        @Override
+        public String toString() {
+            return "Fact(" + id + ")";
+        }
     }
 
     @Test
diff --git 
a/drools-tms/src/main/java/org/drools/tms/agenda/TruthMaintenanceSystemRuleTerminalNodeLeftTuple.java
 
b/drools-tms/src/main/java/org/drools/tms/agenda/TruthMaintenanceSystemRuleTerminalNodeLeftTuple.java
index 7774161c2b..0c0a5db05f 100644
--- 
a/drools-tms/src/main/java/org/drools/tms/agenda/TruthMaintenanceSystemRuleTerminalNodeLeftTuple.java
+++ 
b/drools-tms/src/main/java/org/drools/tms/agenda/TruthMaintenanceSystemRuleTerminalNodeLeftTuple.java
@@ -106,7 +106,7 @@ public class 
TruthMaintenanceSystemRuleTerminalNodeLeftTuple<T extends ModedAsse
                 removeBlocked(dep);
                 TruthMaintenanceSystemRuleTerminalNodeLeftTuple justified = 
(TruthMaintenanceSystemRuleTerminalNodeLeftTuple) dep.getJustified();
                 if (justified.getBlockers().isEmpty() && justified.isActive()) 
{
-                    activationsManager.stageLeftTuple(ruleAgendaItem, 
justified);
+                    
activationsManager.stageLeftTuple(justified.getRuleAgendaItem(), justified);
                 }
                 dep = tmp;
             }


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

Reply via email to