UNOMI-676: fix past event recalculation limited to 50 rules (#510)

* UNOMI-676: fix past event recalculation limited to 50 rules

* UNOMI-676: fix past event recalculation limited to 50 rules

* UNOMI-676: fix past event recalculation limited to 50 rules
diff --git a/api/src/main/java/org/apache/unomi/api/services/RulesService.java b/api/src/main/java/org/apache/unomi/api/services/RulesService.java
index 817e088..52a97ee 100644
--- a/api/src/main/java/org/apache/unomi/api/services/RulesService.java
+++ b/api/src/main/java/org/apache/unomi/api/services/RulesService.java
@@ -26,6 +26,7 @@
 import org.apache.unomi.api.rules.Rule;
 import org.apache.unomi.api.rules.RuleStatistics;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -58,6 +59,15 @@
     PartialList<Rule> getRuleDetails(Query query);
 
     /**
+     * Get all rules available in the system.
+     * (This is not doing a persistence query to retrieve the rules, it's using the internal in memory cache
+     * that is refreshed every second by default but can vary depending on your own configuration)
+     *
+     * @return all rules available.
+     */
+    List<Rule> getAllRules();
+
+    /**
      * Retrieves the rule identified by the specified identifier.
      *
      * @param ruleId the identifier of the rule we want to retrieve
diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
index f1bb826..1f5ebf1 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
@@ -444,7 +444,8 @@
 
     public void createAndWaitForRule(Rule rule) throws InterruptedException {
         rulesService.setRule(rule);
-        keepTrying("Failed waiting for rule to be saved", () -> rulesService.getRule(rule.getMetadata().getId()), Objects::nonNull, 3000,
+        keepTrying("Failed waiting for rule to be saved", () -> rulesService.getAllRules(),
+                (rules) -> rules.stream().anyMatch(r -> r.getItemId().equals(rule.getMetadata().getId())), 1000,
                 100);
         rulesService.refreshRules();
     }
diff --git a/itests/src/test/java/org/apache/unomi/itests/RuleServiceIT.java b/itests/src/test/java/org/apache/unomi/itests/RuleServiceIT.java
index aa88cde..173fbb6 100644
--- a/itests/src/test/java/org/apache/unomi/itests/RuleServiceIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/RuleServiceIT.java
@@ -79,8 +79,32 @@
     }
 
     @Test
-    public void testRuleEventTypeOptimization() throws InterruptedException {
+    public void getAllRulesShouldReturnAllRulesAvailable() throws InterruptedException {
+        String ruleIDBase = "moreThan50RuleTest";
+        int originalRulesNumber = rulesService.getAllRules().size();
+        for (int i = 0; i < 60; i++) {
+            String ruleID = ruleIDBase + "_" + i;
+            Metadata metadata = new Metadata(ruleID);
+            metadata.setName(ruleID);
+            metadata.setDescription(ruleID);
+            metadata.setScope(TEST_SCOPE);
+            Rule nullRule = new Rule(metadata);
+            nullRule.setCondition(null);
+            nullRule.setActions(null);
+            createAndWaitForRule(nullRule);
+        }
+        assertEquals("Expected getAllRules to be able to retrieve all the rules available in the system", originalRulesNumber + 60, rulesService.getAllRules().size());
+        // cleanup
+        for (int i = 0; i < 60; i++) {
+            String ruleID = ruleIDBase + "_" + i;
+            rulesService.removeRule(ruleID);
+        }
+        refreshPersistence();
+        rulesService.refreshRules();
+    }
 
+    @Test
+    public void testRuleEventTypeOptimization() throws InterruptedException {
         ConditionBuilder builder = new ConditionBuilder(definitionsService);
         Rule simpleEventTypeRule = new Rule(new Metadata(TEST_SCOPE, "simple-event-type-rule", "Simple event type rule", "A rule with a simple condition to match an event type"));
         simpleEventTypeRule.setCondition(builder.condition("eventTypeCondition").parameter("eventTypeId", "view").build());
diff --git a/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java
index 56e2e8f..e0ffbee 100644
--- a/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java
@@ -268,7 +268,7 @@
         try {
             // we use local variables to make sure we quickly switch the collections since the refresh is called often
             // we want to avoid concurrency issues with the shared collections
-            List<Rule> newAllRules = getAllRules();
+            List<Rule> newAllRules = queryAllRules();
             this.rulesByEventType = getRulesByEventType(newAllRules);
             this.allRules = newAllRules;
         } catch (Throwable t) {
@@ -276,7 +276,11 @@
         }
     }
 
-    private List<Rule> getAllRules() {
+    public List<Rule> getAllRules() {
+        return Collections.unmodifiableList(allRules);
+    }
+
+    private List<Rule> queryAllRules() {
         List<Rule> rules = persistenceService.getAllItems(Rule.class, 0, -1, "priority").getList();
         for (Rule rule : rules) {
             // Check rule integrity
diff --git a/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java
index 90fda2b..56f1287 100644
--- a/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java
@@ -935,16 +935,17 @@
     public void recalculatePastEventConditions() {
         Set<String> segmentOrScoringIdsToReevaluate = new HashSet<>();
         // reevaluate auto generated rules used to store the event occurrence count on the profile
-        for (Metadata metadata : rulesService.getRuleMetadatas()) {
-            Rule rule = rulesService.getRule(metadata.getId());
-            for (Action action : rule.getActions()) {
-                if (action.getActionTypeId().equals("setEventOccurenceCountAction")) {
-                    Condition pastEventCondition = (Condition) action.getParameterValues().get("pastEventCondition");
-                    if (pastEventCondition.containsParameter("numberOfDays")) {
-                        recalculatePastEventOccurrencesOnProfiles(rule.getCondition(), pastEventCondition, true, true);
-                        logger.info("Event occurrence count on profiles updated for rule: {}", rule.getItemId());
-                        if (rule.getLinkedItems() != null && rule.getLinkedItems().size() > 0) {
-                            segmentOrScoringIdsToReevaluate.addAll(rule.getLinkedItems());
+        for (Rule rule : rulesService.getAllRules()) {
+            if (rule.getActions() != null && rule.getActions().size() > 0) {
+                for (Action action : rule.getActions()) {
+                    if (action.getActionTypeId().equals("setEventOccurenceCountAction")) {
+                        Condition pastEventCondition = (Condition) action.getParameterValues().get("pastEventCondition");
+                        if (pastEventCondition.containsParameter("numberOfDays")) {
+                            recalculatePastEventOccurrencesOnProfiles(rule.getCondition(), pastEventCondition, true, true);
+                            logger.info("Event occurrence count on profiles updated for rule: {}", rule.getItemId());
+                            if (rule.getLinkedItems() != null && rule.getLinkedItems().size() > 0) {
+                                segmentOrScoringIdsToReevaluate.addAll(rule.getLinkedItems());
+                            }
                         }
                     }
                 }