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

jsinovassinnaik pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/unomi.git


The following commit(s) were added to refs/heads/master by this push:
     new ce569e350 UNOMI-885: fix migration error on rollover alias (#716)
ce569e350 is described below

commit ce569e35058cd68d7c93c2f1c4da1f8091d95f48
Author: Jonathan SINOVASSIN-NAIK <[email protected]>
AuthorDate: Fri Mar 7 12:11:03 2025 +0100

    UNOMI-885: fix migration error on rollover alias (#716)
    
    * UNOMI-885: fix migration error on rollover alias
    
    * UNOMI-885: change rollover value to have more than one rollover index 
after migration
    
    * UNOMI-885: update test to check rollover indices after migration
    
    * UNOMI-885: remove the check on duplicate session as indices are rolloved 
during migration
---
 .github/workflows/unomi-ci-build-tests.yml         |  4 +-
 .../test/java/org/apache/unomi/itests/AllITs.java  |  4 +-
 .../test/java/org/apache/unomi/itests/BaseIT.java  |  1 +
 ...20IT.java => Migrate16xToCurrentVersionIT.java} | 15 +++--
 .../shell/migration/utils/MigrationUtils.java      | 74 ++++++++++++++++++++--
 ...-2.2.0-10-rolloverAndMigrateEventSession.groovy |  4 ++
 ...te-2.5.0-00-cleanPastEventProfileSession.groovy | 16 +++--
 .../migrate-2.5.0-10-loginEventScope.groovy        |  1 -
 .../requestBody/2.0.0/base_reindex_request.json    |  3 +-
 .../2.2.0/base_index_withRollover_request.json     |  4 +-
 .../requestBody/2.2.0/base_reindex_request.json    |  3 +-
 .../requestBody/2.2.0/configure_alias_body.json    | 11 ++++
 12 files changed, 114 insertions(+), 26 deletions(-)

diff --git a/.github/workflows/unomi-ci-build-tests.yml 
b/.github/workflows/unomi-ci-build-tests.yml
index d6cb887c6..e4dc433b6 100644
--- a/.github/workflows/unomi-ci-build-tests.yml
+++ b/.github/workflows/unomi-ci-build-tests.yml
@@ -37,13 +37,13 @@ jobs:
       - name: Integration tests
         run: mvn -ntp clean install -Pintegration-tests
       - name: Archive code coverage logs
-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
         if: false # UNOMI-746 Reactivate if necessary
         with:
           name: unomi-code-coverage-jdk11-${{ github.run_number }}
           path: itests/target/site/jacoco
       - name: Archive unomi logs
-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
         if: failure()
         with:
           name: unomi-log-jdk11-${{ github.run_number }}
diff --git a/itests/src/test/java/org/apache/unomi/itests/AllITs.java 
b/itests/src/test/java/org/apache/unomi/itests/AllITs.java
index f415c3ab9..bd9a9a108 100644
--- a/itests/src/test/java/org/apache/unomi/itests/AllITs.java
+++ b/itests/src/test/java/org/apache/unomi/itests/AllITs.java
@@ -17,7 +17,7 @@
 
 package org.apache.unomi.itests;
 
-import org.apache.unomi.itests.migration.Migrate16xTo220IT;
+import org.apache.unomi.itests.migration.Migrate16xToCurrentVersionIT;
 import org.apache.unomi.itests.graphql.*;
 import org.apache.unomi.itests.migration.MigrationIT;
 import org.junit.runner.RunWith;
@@ -31,7 +31,7 @@ import org.junit.runners.Suite.SuiteClasses;
  */
 @RunWith(Suite.class)
 @SuiteClasses({
-        Migrate16xTo220IT.class,
+        Migrate16xToCurrentVersionIT.class,
         MigrationIT.class,
         BasicIT.class,
         ConditionEvaluatorIT.class,
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 1c9407914..38b7f0c66 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
@@ -253,6 +253,7 @@ public abstract class BaseIT extends KarafTestSupport {
                 editConfigurationFilePut("etc/custom.system.properties", 
"org.apache.unomi.elasticsearch.cluster.name", "contextElasticSearchITests"),
                 editConfigurationFilePut("etc/custom.system.properties", 
"org.apache.unomi.elasticsearch.addresses", "localhost:9400"),
                 editConfigurationFilePut("etc/custom.system.properties", 
"org.apache.unomi.elasticsearch.taskWaitingPollingInterval", "50"),
+                editConfigurationFilePut("etc/custom.system.properties", 
"org.apache.unomi.elasticsearch.rollover.maxDocs", "300"),
 
                 
systemProperty("org.ops4j.pax.exam.rbc.rmi.port").value("1199"),
                 
systemProperty("org.apache.unomi.hazelcast.group.name").value("cellar"),
diff --git 
a/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java 
b/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xToCurrentVersionIT.java
similarity index 97%
rename from 
itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java
rename to 
itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xToCurrentVersionIT.java
index f109eda4b..d8c9494ea 100644
--- 
a/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java
+++ 
b/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xToCurrentVersionIT.java
@@ -31,14 +31,13 @@ import org.junit.Test;
 import java.io.IOException;
 import java.util.*;
 
-public class Migrate16xTo220IT extends BaseIT {
+public class Migrate16xToCurrentVersionIT extends BaseIT {
 
     private int eventCount = 0;
     private int sessionCount = 0;
     private Set<String[]> initialScopes = new HashSet<>();
 
     private static final String SCOPE_NOT_EXIST = "SCOPE_NOT_EXIST";
-    private static final int NUMBER_DUPLICATE_SESSIONS = 3;
     private static final List<String> oldSystemItemsIndices = 
Arrays.asList("context-actiontype", "context-campaign", 
"context-campaignevent", "context-goal",
             "context-userlist", "context-propertytype", "context-scope", 
"context-conditiontype", "context-rule", "context-scoring", "context-segment", 
"context-groovyaction", "context-topic",
             "context-patch", "context-jsonschema", "context-importconfig", 
"context-exportconfig", "context-rulestats");
@@ -100,12 +99,12 @@ public class Migrate16xTo220IT extends BaseIT {
         checkPagePathForEventView();
         checkPastEvents();
         checkScopeEventHaveBeenUpdated();
+        countNumberOfSessionIndices();
     }
 
     /**
      * Checks if at least the new index for events and sessions exists.
      * Also checks:
-     * - duplicated sessions are correctly removed (-3 sessions in final count)
      * - persona sessions are now merged in session index due to index 
reduction in 2_2_0 (+2 sessions in final count)
      */
     private void checkEventSessionRollover2_2_0() throws IOException {
@@ -122,7 +121,7 @@ public class Migrate16xTo220IT extends BaseIT {
             newSessioncount += countItems(httpClient, sessionIndex, null);
         }
         Assert.assertEquals(eventCount, newEventcount);
-        Assert.assertEquals(sessionCount - NUMBER_DUPLICATE_SESSIONS, 
newSessioncount);
+        Assert.assertEquals(sessionCount, newSessioncount);
     }
 
     private void checkIndexReductions2_2_0() throws IOException {
@@ -339,6 +338,14 @@ public class Migrate16xTo220IT extends BaseIT {
         }
     }
 
+    private void countNumberOfSessionIndices() {
+        try {
+           Set<String> sessionIndices = 
MigrationUtils.getIndexesPrefixedBy(httpClient, "http://localhost:9400";, 
"context-session");
+            Assert.assertEquals(2, sessionIndices.size());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
     private void getScopeFromEvents(CloseableHttpClient httpClient, String 
eventIndex) throws IOException {
         String requestBody = 
resourceAsString("migration/match_all_login_event_request.json");
         JsonNode jsonNode = 
objectMapper.readTree(HttpUtils.executePostRequest(httpClient, 
"http://localhost:9400"; + "/" + eventIndex + "/_search", requestBody, null));
diff --git 
a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java
 
b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java
index 06d05f535..53cc90a94 100644
--- 
a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java
+++ 
b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java
@@ -97,6 +97,23 @@ public class MigrationUtils {
         }
     }
 
+    public static void configureAlias(CloseableHttpClient httpClient, String 
esAddress, String alias, String writeIndex, Set<String> readIndices, String 
configureAliasBody, MigrationContext context) throws IOException {
+        String readIndicesToAdd = "";
+        if (!readIndices.isEmpty()) {
+            readIndicesToAdd = "," + readIndices.stream().map(index -> 
"{\"add\": {\"index\": \"" + index + "\", \"alias\": \"" + alias + "\", 
\"is_write_index\": false}}").collect(Collectors.joining(","));
+        }
+        if (context != null) {
+            context.printMessage("Will set " + writeIndex + " as write index 
for alias " + alias);
+            context.printMessage("Will set " + readIndices.toString() + " as 
read indices");
+        } else {
+            LOGGER.info("Will set {} as write index for alias {}", writeIndex, 
alias);
+            LOGGER.info("Will set {} as read indices", readIndices.toString());
+        }
+        String requestBody = configureAliasBody.replace("#writeIndexName", 
writeIndex).replace("#aliasName", alias).replace("#readIndicesToAdd", 
readIndicesToAdd);
+
+        HttpUtils.executePostRequest(httpClient, esAddress + "/_aliases", 
requestBody, null);
+    }
+
     public static Set<String> getIndexesPrefixedBy(CloseableHttpClient 
httpClient, String esAddress, String prefix) throws IOException {
         try (CloseableHttpResponse response = httpClient.execute(new 
HttpGet(esAddress + "/_aliases"))) {
             if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
@@ -300,9 +317,9 @@ public class MigrationUtils {
      * <p>This method sends a request to update documents that match the 
provided query in the specified index. The update operation is
      * performed asynchronously, and the method waits for the task to complete 
before returning.</p>
      *
-     * @param httpClient the CloseableHttpClient used to send the request to 
the Elasticsearch server
-     * @param esAddress the address of the Elasticsearch server
-     * @param indexName the name of the index where documents should be updated
+     * @param httpClient  the CloseableHttpClient used to send the request to 
the Elasticsearch server
+     * @param esAddress   the address of the Elasticsearch server
+     * @param indexName   the name of the index where documents should be 
updated
      * @param requestBody the JSON body containing the query and update 
instructions for the documents
      * @throws Exception if there is an error during the HTTP request or while 
waiting for the task to finish
      */
@@ -332,23 +349,66 @@ public class MigrationUtils {
         waitForTaskToFinish(httpClient, esAddress, task.getString("task"), 
null);
     }
 
+    private static void printResponseDetail(JSONObject response, 
MigrationContext migrationContext){
+        StringBuilder sb = new StringBuilder();
+        if (response.has("total")) {
+            sb.append("Total: ").append(response.getInt("total")).append(" ");
+        }
+        if (response.has("updated")) {
+            sb.append("Updated: ").append(response.getInt("updated")).append(" 
");
+        }
+        if (response.has("created")) {
+            sb.append("Created: ").append(response.getInt("created")).append(" 
");
+        }
+        if (response.has("deleted")) {
+            sb.append("Deleted: ").append(response.getInt("deleted")).append(" 
");
+        }
+        if (response.has("batches")) {
+            sb.append("Batches: ").append(response.getInt("batches")).append(" 
");
+        }
+        if (migrationContext != null) {
+            migrationContext.printMessage(sb.toString());
+        } else {
+            LOGGER.info(sb.toString());
+        }
+    }
+
     public static void waitForTaskToFinish(CloseableHttpClient httpClient, 
String esAddress, String taskId, MigrationContext migrationContext) throws 
IOException {
         while (true) {
             final JSONObject status = new JSONObject(
                     HttpUtils.executeGetRequest(httpClient, esAddress + 
"/_tasks/" + taskId,
                             null));
+            if (status.has("error")) {
+                final JSONObject error = status.getJSONObject("error");
+                throw new IOException("Task error: " + error.getString("type") 
+ " - " + error.getString("reason"));
+            }
             if (status.has("completed") && status.getBoolean("completed")) {
                 if (migrationContext != null) {
                     migrationContext.printMessage("Task is completed");
                 } else {
                     LOGGER.info("Task is completed");
                 }
+                if (status.has("response")) {
+                    final JSONObject response = 
status.getJSONObject("response");
+                    printResponseDetail(response, migrationContext);
+                    if (response.has("failures")) {
+                        final JSONArray failures = 
response.getJSONArray("failures");
+                        if (!failures.isEmpty()) {
+                            for (int i = 0; i < failures.length(); i++) {
+                                JSONObject failure = failures.getJSONObject(i);
+                                JSONObject cause = 
failure.getJSONObject("cause");
+                                if (migrationContext != null) {
+                                    migrationContext.printMessage("Cause of 
failure: " + cause.toString());
+                                } else {
+                                    LOGGER.error("Cause of failure: {}", 
cause.toString());
+                                }
+                            }
+                            throw new IOException("Task completed with 
failures, check previous log for details");
+                        }
+                    }
+                }
                 break;
             }
-            if (status.has("error")) {
-                final JSONObject error = status.getJSONObject("error");
-                throw new IOException("Task error: " + error.getString("type") 
+ " - " + error.getString("reason"));
-            }
             if (migrationContext != null) {
                 migrationContext.printMessage("Waiting for Task " + taskId + " 
to complete");
             } else {
diff --git 
a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.2.0-10-rolloverAndMigrateEventSession.groovy
 
b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.2.0-10-rolloverAndMigrateEventSession.groovy
index c692fa7a2..7da6f86c3 100644
--- 
a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.2.0-10-rolloverAndMigrateEventSession.groovy
+++ 
b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.2.0-10-rolloverAndMigrateEventSession.groovy
@@ -45,9 +45,11 @@ context.performMigrationStep("2.2.0-create-event-index", () 
-> {
     if (!MigrationUtils.indexExists(context.getHttpClient(), esAddress, 
newEventIndex)) {
         String baseRequest = MigrationUtils.resourceAsString(bundleContext, 
"requestBody/2.2.0/base_index_withRollover_request.json")
         String mapping = 
MigrationUtils.extractMappingFromBundles(bundleContext, "event.json")
+        String configureAliasBody = 
MigrationUtils.resourceAsString(bundleContext, 
"requestBody/2.2.0/configure_alias_body.json")
 
         String newIndexSettings = 
MigrationUtils.buildIndexCreationRequestWithRollover(baseRequest, mapping, 
context, rolloverPolicyName, rolloverEventAlias)
         HttpUtils.executePutRequest(context.getHttpClient(), esAddress + "/" + 
newEventIndex, newIndexSettings, null)
+        MigrationUtils.configureAlias(context.getHttpClient(), esAddress, 
rolloverEventAlias, newEventIndex, Collections.emptySet(), configureAliasBody, 
context)
     }
 })
 
@@ -73,9 +75,11 @@ context.performMigrationStep("2.2.0-create-session-index", 
() -> {
     if (!MigrationUtils.indexExists(context.getHttpClient(), esAddress, 
newSessionIndex)) {
         String baseRequest = MigrationUtils.resourceAsString(bundleContext, 
"requestBody/2.2.0/base_index_withRollover_request.json")
         String mapping = 
MigrationUtils.extractMappingFromBundles(bundleContext, "session.json")
+        String configureAliasBody = 
MigrationUtils.resourceAsString(bundleContext, 
"requestBody/2.2.0/configure_alias_body.json")
 
         String newIndexSettings = 
MigrationUtils.buildIndexCreationRequestWithRollover(baseRequest, mapping, 
context, rolloverPolicyName, rolloverSessionAlias)
         HttpUtils.executePutRequest(context.getHttpClient(), esAddress + "/" + 
newSessionIndex, newIndexSettings, null)
+        MigrationUtils.configureAlias(context.getHttpClient(), esAddress, 
rolloverSessionAlias, newSessionIndex, Collections.emptySet(), 
configureAliasBody, context)
     }
 })
 
diff --git 
a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-00-cleanPastEventProfileSession.groovy
 
b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-00-cleanPastEventProfileSession.groovy
index 2e45b437d..01d69aec8 100644
--- 
a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-00-cleanPastEventProfileSession.groovy
+++ 
b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-00-cleanPastEventProfileSession.groovy
@@ -1,8 +1,5 @@
 import org.apache.unomi.shell.migration.service.MigrationContext
-import org.apache.unomi.shell.migration.utils.HttpUtils
 import org.apache.unomi.shell.migration.utils.MigrationUtils
-import org.osgi.framework.BundleContext
-import org.osgi.framework.Bundle
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -25,7 +22,7 @@ MigrationContext context = migrationContext
 String esAddress = context.getConfigString("esAddress")
 String indexPrefix = context.getConfigString("indexPrefix")
 String rolloverPolicyName = indexPrefix + "-unomi-rollover-policy"
-String rolloverEventAlias = indexPrefix + "-session"
+String rolloverSessionAlias = indexPrefix + "-session"
 
 context.performMigrationStep("2.5.0-clean-profile-mapping", () -> {
     String baseSettings = MigrationUtils.resourceAsString(bundleContext, 
"requestBody/2.0.0/base_index_mapping.json")
@@ -39,10 +36,17 @@ context.performMigrationStep("2.5.0-clean-session-mapping", 
() -> {
     String baseSettings = MigrationUtils.resourceAsString(bundleContext, 
"requestBody/2.2.0/base_index_withRollover_request.json")
     String cleanPastEventScript = 
MigrationUtils.getFileWithoutComments(bundleContext, 
"requestBody/2.5.0/remove_pastEvents_session.painless")
     String mapping = MigrationUtils.extractMappingFromBundles(bundleContext, 
"session.json")
-    String newIndexSettings = 
MigrationUtils.buildIndexCreationRequestWithRollover(baseSettings, mapping, 
context, rolloverPolicyName, rolloverEventAlias)
+    String newIndexSettings = 
MigrationUtils.buildIndexCreationRequestWithRollover(baseSettings, mapping, 
context, rolloverPolicyName, rolloverSessionAlias)
     Set<String> sessionIndices = 
MigrationUtils.getIndexesPrefixedBy(context.getHttpClient(), esAddress, 
"${indexPrefix}-session-")
+    String configureAliasBody = MigrationUtils.resourceAsString(bundleContext, 
"requestBody/2.2.0/configure_alias_body.json")
 
-    sessionIndices.each { sessionIndex ->
+    Set<String> sortedSet = new TreeSet<>(sessionIndices)
+    sortedSet.each { sessionIndex ->
         MigrationUtils.reIndex(context.getHttpClient(), bundleContext, 
esAddress, sessionIndex, newIndexSettings, cleanPastEventScript, context, 
"2.5.0-clean-session-mapping")
     }
+    SortedSet<String> allExceptLast = Collections.emptySortedSet();
+    if (sortedSet.size() > 1){
+         allExceptLast = sortedSet.headSet(sortedSet.last());
+    }
+    MigrationUtils.configureAlias(context.getHttpClient(), esAddress, 
rolloverSessionAlias, sortedSet.last(), allExceptLast, configureAliasBody, 
context)
 })
diff --git 
a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-10-loginEventScope.groovy
 
b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-10-loginEventScope.groovy
index 967bc5714..890e93981 100644
--- 
a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-10-loginEventScope.groovy
+++ 
b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-10-loginEventScope.groovy
@@ -1,5 +1,4 @@
 import org.apache.unomi.shell.migration.service.MigrationContext
-import org.apache.unomi.shell.migration.utils.HttpUtils
 import org.apache.unomi.shell.migration.utils.MigrationUtils
 
 /*
diff --git 
a/tools/shell-commands/src/main/resources/requestBody/2.0.0/base_reindex_request.json
 
b/tools/shell-commands/src/main/resources/requestBody/2.0.0/base_reindex_request.json
index 589e71084..814b8d223 100644
--- 
a/tools/shell-commands/src/main/resources/requestBody/2.0.0/base_reindex_request.json
+++ 
b/tools/shell-commands/src/main/resources/requestBody/2.0.0/base_reindex_request.json
@@ -1,6 +1,7 @@
 {
   "source": {
-    "index": "#source"
+    "index": "#source",
+    "size": 5000
   },
   "dest": {
     "index": "#dest"
diff --git 
a/tools/shell-commands/src/main/resources/requestBody/2.2.0/base_index_withRollover_request.json
 
b/tools/shell-commands/src/main/resources/requestBody/2.2.0/base_index_withRollover_request.json
index c59422642..442d2d1b5 100644
--- 
a/tools/shell-commands/src/main/resources/requestBody/2.2.0/base_index_withRollover_request.json
+++ 
b/tools/shell-commands/src/main/resources/requestBody/2.2.0/base_index_withRollover_request.json
@@ -23,8 +23,8 @@
   },
   "aliases": {
     "#lifecycleRolloverAlias": {
-      "is_write_index": true
+      "is_write_index": false
     }
   },
   "mappings": #mappings
-}
\ No newline at end of file
+}
diff --git 
a/tools/shell-commands/src/main/resources/requestBody/2.2.0/base_reindex_request.json
 
b/tools/shell-commands/src/main/resources/requestBody/2.2.0/base_reindex_request.json
index 589e71084..814b8d223 100644
--- 
a/tools/shell-commands/src/main/resources/requestBody/2.2.0/base_reindex_request.json
+++ 
b/tools/shell-commands/src/main/resources/requestBody/2.2.0/base_reindex_request.json
@@ -1,6 +1,7 @@
 {
   "source": {
-    "index": "#source"
+    "index": "#source",
+    "size": 5000
   },
   "dest": {
     "index": "#dest"
diff --git 
a/tools/shell-commands/src/main/resources/requestBody/2.2.0/configure_alias_body.json
 
b/tools/shell-commands/src/main/resources/requestBody/2.2.0/configure_alias_body.json
new file mode 100644
index 000000000..4016c0f9b
--- /dev/null
+++ 
b/tools/shell-commands/src/main/resources/requestBody/2.2.0/configure_alias_body.json
@@ -0,0 +1,11 @@
+{
+  "actions": [
+    {
+      "add": {
+        "index": "#writeIndexName",
+        "alias": "#aliasName",
+        "is_write_index": true
+      }
+    }#readIndicesToAdd
+  ]
+}

Reply via email to