UNOMI-557: Optimize the profile update during segment deletion (#433)

* UNOMI-557: Optimize the profile update during segment deletion

* UNOMI-557: Optimize the profile update during segment deletion

* UNOMI-557: Optimize the profile update during segment deletion

* UNOMI-557: Optimize the profile update during segment deletion

* UNOMI-557: Optimize the profile update during segment deletion
diff --git a/itests/src/test/java/org/apache/unomi/itests/SegmentIT.java b/itests/src/test/java/org/apache/unomi/itests/SegmentIT.java
index 221f975..1eb0371 100644
--- a/itests/src/test/java/org/apache/unomi/itests/SegmentIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/SegmentIT.java
@@ -162,6 +162,45 @@
     }
 
     @Test
+    public void testProfileEngagedSegmentAddedRemoved() throws InterruptedException {
+        Condition segmentSearchCondition = new Condition();
+        segmentSearchCondition.setConditionType(definitionsService.getConditionType("profilePropertyCondition"));
+        segmentSearchCondition.setParameter("propertyName", "segments");
+        segmentSearchCondition.setParameter("comparisonOperator", "equals");
+        segmentSearchCondition.setParameter("propertyValue", "add-delete-segment-test");
+
+        // create Profile
+        Profile profile = new Profile();
+        profile.setItemId("test_profile_id");
+        profile.setProperty("age", 42);
+        profileService.save(profile);
+        persistenceService.refreshIndex(Profile.class, null);
+
+        keepTrying("Profile should not be engaged in the segment yet", () -> persistenceService.query(segmentSearchCondition, null, Profile.class),
+                profiles -> profiles.size() == 0, 1000, 20);
+
+        // create the segment
+        Metadata segmentMetadata = new Metadata("add-delete-segment-test");
+        Segment segment = new Segment(segmentMetadata);
+        Condition segmentCondition = new Condition(definitionsService.getConditionType("profilePropertyCondition"));
+        segmentCondition.setParameter("propertyName", "properties.age");
+        segmentCondition.setParameter("comparisonOperator", "exists");
+        segment.setCondition(segmentCondition);
+        segmentService.setSegmentDefinition(segment);
+
+        // insure the profile that did the past event condition is correctly engaged in the segment.
+        keepTrying("Profile should be engaged in the segment", () -> persistenceService.query(segmentSearchCondition, null, Profile.class),
+                profiles -> profiles.size() == 1, 1000, 20);
+
+        // delete the segment
+        segmentService.removeSegmentDefinition("add-delete-segment-test", false);
+
+        // insure the profile is not engaged anymore after segment deleted
+        keepTrying("Profile should not be engaged in the segment anymore after the segment have been deleted", () -> persistenceService.query(segmentSearchCondition, null, Profile.class),
+                profiles -> profiles.size() == 0, 1000, 20);
+    }
+
+    @Test
     public void testSegmentWithPastEventCondition() throws InterruptedException {
         // create Profile
         Profile profile = new Profile();
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 dc1333b..90fda2b 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
@@ -391,21 +391,7 @@
             segmentCondition.setParameter("propertyName", "segments");
             segmentCondition.setParameter("comparisonOperator", "equals");
             segmentCondition.setParameter("propertyValue", segmentId);
-
-            List<Profile> previousProfiles = persistenceService.query(segmentCondition, null, Profile.class);
-            long updatedProfileCount = 0;
-            long profileRemovalStartTime = System.currentTimeMillis();
-            if (batchSegmentProfileUpdate && previousProfiles.size() > 0) {
-                batchUpdateProfilesSegment(segmentId, previousProfiles, false);
-            } else {
-                for (Profile profileToRemove : previousProfiles) {
-                    Map<String, Object> sourceMap = buildPropertiesMapForUpdateSegment(profileToRemove, segmentId, false);
-                    persistenceService.update(profileToRemove, null, Profile.class, sourceMap);
-                }
-            }
-
-            updatedProfileCount += previousProfiles.size();
-            logger.info("Removed segment from {} profiles in {} ms", updatedProfileCount, System.currentTimeMillis() - profileRemovalStartTime);
+            updateProfilesSegment(segmentCondition, segmentId, false, false);
 
             // update impacted segments
             for (Segment segment : impactedSegments) {
@@ -1088,15 +1074,15 @@
             profilesToRemoveSubConditions.add(notNewSegmentCondition);
             profilesToRemoveCondition.setParameter("subConditions", profilesToRemoveSubConditions);
 
-            updatedProfileCount += updateProfilesSegment(profilesToAddCondition, segmentId, true);
-            updatedProfileCount += updateProfilesSegment(profilesToRemoveCondition, segmentId, false);
+            updatedProfileCount += updateProfilesSegment(profilesToAddCondition, segmentId, true, sendProfileUpdateEventForSegmentUpdate);
+            updatedProfileCount += updateProfilesSegment(profilesToRemoveCondition, segmentId, false, sendProfileUpdateEventForSegmentUpdate);
         } else {
-            updatedProfileCount += updateProfilesSegment(segmentCondition, segmentId, false);
+            updatedProfileCount += updateProfilesSegment(segmentCondition, segmentId, false, sendProfileUpdateEventForSegmentUpdate);
         }
         logger.info("{} profiles updated in {}ms", updatedProfileCount, System.currentTimeMillis() - updateProfilesForSegmentStartTime);
     }
 
-    private long updateProfilesSegment(Condition profilesToUpdateCondition, String segmentId, boolean isAdd) {
+    private long updateProfilesSegment(Condition profilesToUpdateCondition, String segmentId, boolean isAdd, boolean sendProfileUpdateEvent) {
         long updatedProfileCount = 0;
         PartialList<Profile> profiles = persistenceService.query(profilesToUpdateCondition, null, Profile.class, 0, segmentUpdateBatchSize, "10m");
 
@@ -1110,7 +1096,7 @@
                     persistenceService.update(profileToUpdate, null, Profile.class, sourceMap);
                 }
             }
-            if (sendProfileUpdateEventForSegmentUpdate)
+            if (sendProfileUpdateEvent)
                 sendProfileUpdatedEvent(profiles.getList());
 
             updatedProfileCount += profiles.size();