diff --git a/data-migrator/core/src/main/java/io/camunda/migration/data/impl/history/migrator/ProcessInstanceMigrator.java b/data-migrator/core/src/main/java/io/camunda/migration/data/impl/history/migrator/ProcessInstanceMigrator.java index d68ac8edf..ce0369a6c 100644 --- a/data-migrator/core/src/main/java/io/camunda/migration/data/impl/history/migrator/ProcessInstanceMigrator.java +++ b/data-migrator/core/src/main/java/io/camunda/migration/data/impl/history/migrator/ProcessInstanceMigrator.java @@ -29,6 +29,7 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; +import java.util.Objects; import org.camunda.bpm.engine.history.HistoricActivityInstance; import org.camunda.bpm.engine.history.HistoricProcessInstance; import org.springframework.stereotype.Service; @@ -90,6 +91,7 @@ public Long migrateTransactionally(HistoricProcessInstance c7ProcessInstance) { var builder = new ProcessInstanceDbModelBuilder(); Long processInstanceKey = getNextKey(); + Long rootProcessInstanceKey = null; builder.processInstanceKey(processInstanceKey); if (processDefinitionKey != null) { builder.processDefinitionKey(processDefinitionKey); @@ -112,6 +114,7 @@ public Long migrateTransactionally(HistoricProcessInstance c7ProcessInstance) { } else if (c7RootProcessInstanceId != null && isMigrated(c7RootProcessInstanceId, HISTORY_PROCESS_INSTANCE)) { ProcessInstanceEntity rootProcessInstance = findProcessInstanceByC7Id(c7RootProcessInstanceId); if (rootProcessInstance != null && rootProcessInstance.processInstanceKey() != null) { + rootProcessInstanceKey = rootProcessInstance.processInstanceKey(); builder.rootProcessInstanceKey(rootProcessInstance.processInstanceKey()); } } @@ -123,7 +126,8 @@ public Long migrateTransactionally(HistoricProcessInstance c7ProcessInstance) { builder .historyCleanupDate(c8HistoryCleanupDate) - .endDate(c8EndTime); + .endDate(c8EndTime) + .treePath(generateTreepath(rootProcessInstanceKey, processInstanceKey)); ProcessInstanceDbModel dbModel = convert(C7Entity.of(c7ProcessInstance), builder); @@ -176,5 +180,20 @@ protected void resolveParentFlowNodeInstanceKey( } } + /** + * Generates a tree path for process instances in the format: + * PI_rootProcessInstanceKey/PI_processInstanceKey or + * PI_processInstanceKey if this instance is the root of the hierarchy + * + * @param rootProcessInstanceKey the root process instance key + * @param processInstanceKey the process instance key + * @return the tree path string + */ + public static String generateTreepath(Long rootProcessInstanceKey, Long processInstanceKey) { + return rootProcessInstanceKey == null || Objects.equals(rootProcessInstanceKey, processInstanceKey) ? + "PI_" + processInstanceKey : + "PI_" + rootProcessInstanceKey + "/PI_" + processInstanceKey; + } + } diff --git a/data-migrator/core/src/main/java/io/camunda/migration/data/impl/interceptor/history/entity/ProcessInstanceTransformer.java b/data-migrator/core/src/main/java/io/camunda/migration/data/impl/interceptor/history/entity/ProcessInstanceTransformer.java index b0a50d01b..3ed947786 100644 --- a/data-migrator/core/src/main/java/io/camunda/migration/data/impl/interceptor/history/entity/ProcessInstanceTransformer.java +++ b/data-migrator/core/src/main/java/io/camunda/migration/data/impl/interceptor/history/entity/ProcessInstanceTransformer.java @@ -44,7 +44,6 @@ public void execute(HistoricProcessInstance entity, ProcessInstanceDbModelBuilde .tenantId(getTenantId(entity.getTenantId())) .version(entity.getProcessDefinitionVersion()) .tags(getDefaultTags(entity)) - .treePath(null) .numIncidents(0) .partitionId(C7_HISTORY_PARTITION_ID); } diff --git a/data-migrator/qa/integration-tests/src/test/java/io/camunda/migration/data/qa/history/entity/HistoryProcessInstanceTest.java b/data-migrator/qa/integration-tests/src/test/java/io/camunda/migration/data/qa/history/entity/HistoryProcessInstanceTest.java index 1aaf8f779..b0fa41c38 100644 --- a/data-migrator/qa/integration-tests/src/test/java/io/camunda/migration/data/qa/history/entity/HistoryProcessInstanceTest.java +++ b/data-migrator/qa/integration-tests/src/test/java/io/camunda/migration/data/qa/history/entity/HistoryProcessInstanceTest.java @@ -172,6 +172,32 @@ public void shouldCheckCalledProcessParentElementKey() { assertThat(searchHistoricProcessInstances("calledProcessInstanceId")).isEmpty(); } + @Test + public void shouldPopulateTreePathForCallActivity() { + // given + deployer.deployCamunda7Process("callActivityProcess.bpmn"); + deployer.deployCamunda7Process("calledActivitySubprocess.bpmn"); + runtimeService.startProcessInstanceByKey("callingProcessId"); + + // when + historyMigrator.migrate(); + historyMigrator.retry(); + + // then + List parentProcessInstances = searchHistoricProcessInstances("callingProcessId"); + List subProcessInstances = searchHistoricProcessInstances("calledProcessInstanceId"); + assertThat(parentProcessInstances).hasSize(1); + assertThat(subProcessInstances).hasSize(1); + + ProcessInstanceEntity parent = parentProcessInstances.getFirst(); + ProcessInstanceEntity sub = subProcessInstances.getFirst(); + + assertThat(parent.treePath()).isNotNull().isEqualTo("PI_" + parent.processInstanceKey()); + + assertThat(sub.treePath()).isNotNull() + .isEqualTo("PI_" + parent.processInstanceKey() + "/PI_" + sub.processInstanceKey()); + } + @Test public void shouldPopulateRootProcessInstanceKeyForCallActivity() { // given @@ -196,7 +222,7 @@ public void shouldPopulateRootProcessInstanceKeyForCallActivity() { // Sub process should have rootProcessInstanceKey pointing to the parent assertThat(sub.rootProcessInstanceKey()).isEqualTo(parent.processInstanceKey()); - + // Verify that flow nodes also have rootProcessInstanceKey List subFlowNodes = searchHistoricFlowNodes(sub.processInstanceKey()); assertThat(subFlowNodes).isNotEmpty(); @@ -310,7 +336,13 @@ protected void verifyProcessInstanceFields(ProcessInstanceEntity processInstance } assertThat(processInstance.hasIncident()).isEqualTo(hasIncidents); - assertThat(processInstance.treePath()).isNull(); + + assertThat(processInstance.treePath()).isNotNull(); + if (hasParent) { + assertThat(processInstance.treePath()).matches("PI_\\d+/PI_" + processInstance.processInstanceKey()); + } else { + assertThat(processInstance.treePath()).isEqualTo("PI_" + processInstance.processInstanceKey()); + } } @Test