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

xxyu pushed a commit to branch kylin5
in repository https://gitbox.apache.org/repos/asf/kylin.git

commit 1612a76dfafaaab68354b6050beb28ae9cff5c6b
Author: lixiang <447399...@qq.com>
AuthorDate: Fri Mar 17 20:29:41 2023 +0800

    KYLIN-5572 Add a new REST API to build the specified indexes
---
 .../common/exception/code/ErrorCodeServer.java     |   3 +
 .../resources/kylin_error_msg_conf_cn.properties   |   4 +-
 .../resources/kylin_error_msg_conf_en.properties   |   3 +
 .../kylin_error_suggestion_conf_cn.properties      |   3 +
 .../kylin_error_suggestion_conf_en.properties      |   3 +
 .../main/resources/kylin_errorcode_conf.properties |   3 +
 .../kylin/rest/controller/SegmentController.java   |   5 +
 .../controller/open/OpenSegmentController.java     |  59 +++++++++++-
 .../rest/controller/SegmentControllerTest.java     |  38 +++++++-
 .../controller/open/OpenSegmentControllerTest.java | 102 ++++++++++++++++++++-
 10 files changed, 216 insertions(+), 7 deletions(-)

diff --git 
a/src/core-common/src/main/java/org/apache/kylin/common/exception/code/ErrorCodeServer.java
 
b/src/core-common/src/main/java/org/apache/kylin/common/exception/code/ErrorCodeServer.java
index c2d6c51c0c..5e0df273eb 100644
--- 
a/src/core-common/src/main/java/org/apache/kylin/common/exception/code/ErrorCodeServer.java
+++ 
b/src/core-common/src/main/java/org/apache/kylin/common/exception/code/ErrorCodeServer.java
@@ -60,6 +60,9 @@ public enum ErrorCodeServer implements ErrorCodeProducer {
     SEGMENT_STATUS("KE-010022217"),
     SEGMENT_MERGE_CHECK_INDEX_ILLEGAL("KE-010022218"),
     SEGMENT_MERGE_CHECK_PARTITION_ILLEGAL("KE-010022219"),
+    SEGMENT_INDEX_CONFLICT_PARAMETER("KE-010022220"),
+    SEGMENT_INDEX_STATUS_INVALID("KE-010022221"),
+    SEGMENT_SINGLE_JOB_THRESHOLD("KE-010022222"),
 
     // 100072XX table
     TABLE_RELOAD_MODEL_RETRY("KE-010007204"),
diff --git 
a/src/core-common/src/main/resources/kylin_error_msg_conf_cn.properties 
b/src/core-common/src/main/resources/kylin_error_msg_conf_cn.properties
index 3b4eb00a04..0edf55b29c 100644
--- a/src/core-common/src/main/resources/kylin_error_msg_conf_cn.properties
+++ b/src/core-common/src/main/resources/kylin_error_msg_conf_cn.properties
@@ -60,7 +60,9 @@ KE-010022216=Segment “%s” 被锁定,无法删除、刷新或合并。请
 KE-010022217=Segment “%s” 处于 “%s” 状态,无法刷新或合并。请稍后重试。
 KE-010022218=当前 Segments 所包含的索引不一致,请先构建索引并确保其一致后再合并。
 KE-010022219=当前 Segments 所包含的分区不一致,请先构建分区并确保其一致后再合并。
-
+KE-010022220=index_ids或index_status不能同时设置,请修改后重试。
+KE-010022221=索引状态错误,请输入正确的索引状态(NO_BUILD, ONLINE, BUILDING)后重试。
+KE-010022222=单个任务中最多包含100个Segments,请修改后重试。
 
 ## 100072XX table
 KE-010007204=源表 %1$s 中列 %2$s 的数据类型发生变更。请从模型 %3$s 中删除该列,或修改该列的数据类型。
diff --git 
a/src/core-common/src/main/resources/kylin_error_msg_conf_en.properties 
b/src/core-common/src/main/resources/kylin_error_msg_conf_en.properties
index e5dd9f4fb6..132c78cdb3 100644
--- a/src/core-common/src/main/resources/kylin_error_msg_conf_en.properties
+++ b/src/core-common/src/main/resources/kylin_error_msg_conf_en.properties
@@ -60,6 +60,9 @@ KE-010022216=Can't remove, refresh or merge segment "%s", as 
it's LOCKED. Please
 KE-010022217=Can't refresh or merge segment "%s", as it's in "%s". Please try 
again later.
 KE-010022218=The indexes included in the selected segments are not consistent. 
Please build index first and try merging again.
 KE-010022219=The partitions included in the selected segments are not 
consistent. Please build the partitions first and try merging again.
+KE-010022220=Index_ids or index_status can not be set at the same time, please 
modify and try again.
+KE-010022221=The index status is wrong, please enter the correct index 
status(NO_BUILD, ONLINE, BUILDING) and try again.
+KE-010022222=A single job can contain up to 100 segments, please modify and 
try again.
 
 ## 100072XX table
 KE-010007204=The data type of column %2$s from the source table %1$s has 
changed. Please remove the column from model %3$s, or modify the data type.
diff --git 
a/src/core-common/src/main/resources/kylin_error_suggestion_conf_cn.properties 
b/src/core-common/src/main/resources/kylin_error_suggestion_conf_cn.properties
index b9b1865c7b..42dc91cf84 100644
--- 
a/src/core-common/src/main/resources/kylin_error_suggestion_conf_cn.properties
+++ 
b/src/core-common/src/main/resources/kylin_error_suggestion_conf_cn.properties
@@ -58,6 +58,9 @@ KE-010022216=
 KE-010022217=
 KE-010022218=
 KE-010022219=
+KE-010022220=
+KE-010022221=
+KE-010022222=
 
 ## 100072XX table
 KE-010007204=
diff --git 
a/src/core-common/src/main/resources/kylin_error_suggestion_conf_en.properties 
b/src/core-common/src/main/resources/kylin_error_suggestion_conf_en.properties
index 53dc857806..105f521360 100644
--- 
a/src/core-common/src/main/resources/kylin_error_suggestion_conf_en.properties
+++ 
b/src/core-common/src/main/resources/kylin_error_suggestion_conf_en.properties
@@ -58,6 +58,9 @@ KE-010022216=
 KE-010022217=
 KE-010022218=
 KE-010022219=
+KE-010022220=
+KE-010022221=
+KE-010022222=
 
 ## 100072XX table
 KE-010007204=
diff --git a/src/core-common/src/main/resources/kylin_errorcode_conf.properties 
b/src/core-common/src/main/resources/kylin_errorcode_conf.properties
index 3b891fbf05..ae53e187e4 100644
--- a/src/core-common/src/main/resources/kylin_errorcode_conf.properties
+++ b/src/core-common/src/main/resources/kylin_errorcode_conf.properties
@@ -59,6 +59,9 @@ KE-010022214
 KE-010022215
 KE-010022216
 KE-010022217
+KE-010022220
+KE-010022221
+KE-010022222
 
 ## 100072XX table
 KE-010007204
diff --git 
a/src/data-loading-server/src/main/java/org/apache/kylin/rest/controller/SegmentController.java
 
b/src/data-loading-server/src/main/java/org/apache/kylin/rest/controller/SegmentController.java
index cd2701948a..594dd90ef4 100644
--- 
a/src/data-loading-server/src/main/java/org/apache/kylin/rest/controller/SegmentController.java
+++ 
b/src/data-loading-server/src/main/java/org/apache/kylin/rest/controller/SegmentController.java
@@ -22,6 +22,7 @@ import static 
org.apache.kylin.common.constant.HttpConstant.HTTP_VND_APACHE_KYLI
 import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.SEGMENT_EMPTY_ID;
 import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.SEGMENT_MERGE_LESS_THAN_TWO;
 import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.SEGMENT_REFRESH_SELECT_EMPTY;
+import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.SEGMENT_SINGLE_JOB_THRESHOLD;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -323,6 +324,10 @@ public class SegmentController extends BaseController {
         ProjectInstance prjInstance = 
NProjectManager.getInstance(KylinConfig.getInstanceFromEnv())
                 .getProject(buildSegmentsRequest.getProject());
         checkParamLength("tag", buildSegmentsRequest.getTag(), 
prjInstance.getConfig().getJobTagMaxSize());
+        if (!buildSegmentsRequest.isParallelBuildBySegment() && 
buildSegmentsRequest.getSegmentIds() != null
+                && buildSegmentsRequest.getSegmentIds().size() > 100) {
+            throw new KylinException(SEGMENT_SINGLE_JOB_THRESHOLD);
+        }
         val response = fusionModelService.addIndexesToSegments(modelId, 
buildSegmentsRequest);
         return new EnvelopeResponse<>(KylinException.CODE_SUCCESS, response, 
"");
     }
diff --git 
a/src/data-loading-server/src/main/java/org/apache/kylin/rest/controller/open/OpenSegmentController.java
 
b/src/data-loading-server/src/main/java/org/apache/kylin/rest/controller/open/OpenSegmentController.java
index 63eaf1a3da..c528f8b39f 100644
--- 
a/src/data-loading-server/src/main/java/org/apache/kylin/rest/controller/open/OpenSegmentController.java
+++ 
b/src/data-loading-server/src/main/java/org/apache/kylin/rest/controller/open/OpenSegmentController.java
@@ -22,15 +22,24 @@ import static 
org.apache.kylin.common.constant.HttpConstant.HTTP_VND_APACHE_KYLI
 import static 
org.apache.kylin.common.exception.ServerErrorCode.INVALID_PARAMETER;
 import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.MODEL_NAME_NOT_EXIST;
 import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.PROJECT_MULTI_PARTITION_DISABLE;
+import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.SEGMENT_INDEX_CONFLICT_PARAMETER;
+import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.SEGMENT_INDEX_STATUS_INVALID;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
+import java.util.stream.Collectors;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.exception.KylinException;
 import org.apache.kylin.common.exception.ServerErrorCode;
 import org.apache.kylin.common.msg.MsgPicker;
 import org.apache.kylin.common.util.Pair;
+import org.apache.kylin.job.execution.JobTypeEnum;
+import org.apache.kylin.metadata.cube.model.IndexEntity;
 import org.apache.kylin.metadata.model.NDataModel;
 import org.apache.kylin.metadata.model.NDataModelManager;
 import org.apache.kylin.metadata.project.NProjectManager;
@@ -48,12 +57,16 @@ import org.apache.kylin.rest.response.BuildIndexResponse;
 import org.apache.kylin.rest.response.CheckSegmentResponse;
 import org.apache.kylin.rest.response.DataResult;
 import org.apache.kylin.rest.response.EnvelopeResponse;
+import org.apache.kylin.rest.response.IndexResponse;
 import org.apache.kylin.rest.response.JobInfoResponse;
 import org.apache.kylin.rest.response.JobInfoResponseWithFailure;
 import org.apache.kylin.rest.response.NDataSegmentResponse;
 import org.apache.kylin.rest.response.SegmentPartitionResponse;
+import org.apache.kylin.rest.service.FusionIndexService;
 import org.apache.kylin.rest.service.FusionModelService;
 import org.apache.kylin.rest.service.ModelService;
+import org.apache.kylin.rest.service.params.IndexPlanParams;
+import org.apache.kylin.rest.service.params.PaginationParams;
 import org.apache.kylin.rest.util.AclEvaluate;
 import org.apache.kylin.util.DataRangeUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -90,6 +103,9 @@ public class OpenSegmentController extends BaseController {
     @Autowired
     private AclEvaluate aclEvaluate;
 
+    @Autowired
+    private FusionIndexService fusionIndexService;
+
     @VisibleForTesting
     public NDataModel getModel(String modelAlias, String project) {
         NDataModel model = modelService.getManager(NDataModelManager.class, 
project).listAllModels().stream() //
@@ -203,9 +219,10 @@ public class OpenSegmentController extends BaseController {
             @RequestParam(value = "partial_build", required = false, 
defaultValue = "false") boolean partialBuild,
             @RequestParam(value = "priority", required = false, defaultValue = 
"3") Integer priority,
             @RequestParam(value = "yarn_queue", required = false) String 
yarnQueue,
-            @RequestParam(value = "tag", required = false) Object tag) {
+            @RequestParam(value = "tag", required = false) Object tag,
+            @RequestParam(value = "index_status", required = false) 
List<String> indexStatusStr) {
         String projectName = checkProjectName(project);
-        checkSegmentParams(ids, names);
+        checkParams(ids, names, batchIndexIds, indexStatusStr);
         String modelId = getModel(modelAlias, projectName).getUuid();
         Pair<String, String[]> pair = 
fusionModelService.convertSegmentIdWithName(modelId, projectName, ids, names);
         IndexesToSegmentsRequest req = new IndexesToSegmentsRequest();
@@ -213,6 +230,21 @@ public class OpenSegmentController extends BaseController {
         req.setParallelBuildBySegment(parallel);
         req.setSegmentIds(Lists.newArrayList(pair.getSecond()));
         req.setPartialBuild(partialBuild);
+        if (CollectionUtils.isNotEmpty(indexStatusStr)) {
+            List<IndexEntity.Status> indexStatus = 
formatStatus(indexStatusStr);
+            IndexPlanParams indexPlanParams = new IndexPlanParams(project, 
modelId, null, null, Collections.emptyList(),
+                    indexStatus, null);
+            PaginationParams paginationParams = new PaginationParams(null, 
null, null, false);
+            val indexes = fusionIndexService.getIndexes(indexPlanParams, 
paginationParams, null);
+            if (indexes.isEmpty()) {
+                JobInfoResponseWithFailure result = new 
JobInfoResponseWithFailure();
+                List<JobInfoResponse.JobInfo> jobs = new LinkedList<>();
+                jobs.add(new 
JobInfoResponse.JobInfo(JobTypeEnum.INDEX_BUILD.toString(), null));
+                result.setJobs(jobs);
+                return new EnvelopeResponse<>(KylinException.CODE_SUCCESS, 
result, "");
+            }
+            batchIndexIds = 
indexes.stream().map(IndexResponse::getId).collect(Collectors.toList());
+        }
         req.setIndexIds(batchIndexIds);
         req.setPriority(priority);
         req.setYarnQueue(yarnQueue);
@@ -220,6 +252,29 @@ public class OpenSegmentController extends BaseController {
         return segmentController.addIndexesToSegments(pair.getFirst(), req);
     }
 
+    private void checkParams(String[] ids, String[] names, List<Long> 
batchIndexIds, List<String> indexStatus) {
+        checkSegmentParams(ids, names);
+        if (CollectionUtils.isNotEmpty(batchIndexIds) && 
CollectionUtils.isNotEmpty(indexStatus)) {
+            throw new KylinException(SEGMENT_INDEX_CONFLICT_PARAMETER);
+        }
+    }
+
+    private List<IndexEntity.Status> formatStatus(List<String> indexStatus) {
+        List<IndexEntity.Status> result = new ArrayList<>();
+        indexStatus.forEach(str -> {
+            try {
+                IndexEntity.Status status = 
IndexEntity.Status.valueOf(str.toUpperCase(Locale.ROOT));
+                if (status == IndexEntity.Status.LOCKED) {
+                    throw new KylinException(SEGMENT_INDEX_STATUS_INVALID);
+                }
+                result.add(status);
+            } catch (Exception e) {
+                throw new KylinException(SEGMENT_INDEX_STATUS_INVALID);
+            }
+        });
+        return result;
+    }
+
     @ApiOperation(value = "buildIndicesManually", tags = { "AI" })
     @PostMapping(value = "/{model_name:.+}/indexes")
     @ResponseBody
diff --git 
a/src/data-loading-server/src/test/java/org/apache/kylin/rest/controller/SegmentControllerTest.java
 
b/src/data-loading-server/src/test/java/org/apache/kylin/rest/controller/SegmentControllerTest.java
index fbf01832d8..c36bf4b87b 100644
--- 
a/src/data-loading-server/src/test/java/org/apache/kylin/rest/controller/SegmentControllerTest.java
+++ 
b/src/data-loading-server/src/test/java/org/apache/kylin/rest/controller/SegmentControllerTest.java
@@ -24,17 +24,20 @@ import static org.mockito.Mockito.when;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 import org.apache.kylin.common.util.JsonUtil;
+import org.apache.kylin.common.util.NLocalFileMetadataTestCase;
 import org.apache.kylin.common.util.RandomUtil;
 import org.apache.kylin.job.execution.JobTypeEnum;
 import org.apache.kylin.metadata.model.PartitionDesc;
 import org.apache.kylin.metadata.model.Segments;
 import org.apache.kylin.rest.constant.Constant;
-import org.apache.kylin.common.util.NLocalFileMetadataTestCase;
 import org.apache.kylin.rest.request.BuildIndexRequest;
 import org.apache.kylin.rest.request.BuildSegmentsRequest;
 import org.apache.kylin.rest.request.IncrementBuildSegmentsRequest;
+import org.apache.kylin.rest.request.IndexesToSegmentsRequest;
 import org.apache.kylin.rest.request.PartitionsBuildRequest;
 import org.apache.kylin.rest.request.PartitionsRefreshRequest;
 import org.apache.kylin.rest.request.SegmentFixRequest;
@@ -425,4 +428,37 @@ public class SegmentControllerTest extends 
NLocalFileMetadataTestCase {
                 .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_JSON)))
                 .andExpect(MockMvcResultMatchers.status().isOk());
     }
+
+    @Test
+    public void testAddIndexToSegment() throws Exception {
+        IndexesToSegmentsRequest request = new IndexesToSegmentsRequest();
+        request.setSegmentIds(IntStream.rangeClosed(1, 101).mapToObj(t -> t + 
"").collect(Collectors.toList()));
+        request.setProject("default");
+        mockMvc.perform(MockMvcRequestBuilders
+                .post("/api/models/{model}/model_segments/indexes", 
"89af4ee2-2cdb-4b07-b39e-4c29856309aa")
+                
.contentType(MediaType.APPLICATION_JSON).content(JsonUtil.writeValueAsString(request))
+                .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_JSON)))
+                
.andExpect(MockMvcResultMatchers.status().isInternalServerError());
+
+        request.setParallelBuildBySegment(true);
+        mockMvc.perform(MockMvcRequestBuilders
+                .post("/api/models/{model}/model_segments/indexes", 
"89af4ee2-2cdb-4b07-b39e-4c29856309aa")
+                
.contentType(MediaType.APPLICATION_JSON).content(JsonUtil.writeValueAsString(request))
+                .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_JSON)))
+                .andExpect(MockMvcResultMatchers.status().isOk());
+
+        request.setSegmentIds(IntStream.rangeClosed(1, 10).mapToObj(t -> t + 
"").collect(Collectors.toList()));
+        mockMvc.perform(MockMvcRequestBuilders
+                .post("/api/models/{model}/model_segments/indexes", 
"89af4ee2-2cdb-4b07-b39e-4c29856309aa")
+                
.contentType(MediaType.APPLICATION_JSON).content(JsonUtil.writeValueAsString(request))
+                .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_JSON)))
+                .andExpect(MockMvcResultMatchers.status().isOk());
+
+        request.setParallelBuildBySegment(false);
+        mockMvc.perform(MockMvcRequestBuilders
+                .post("/api/models/{model}/model_segments/indexes", 
"89af4ee2-2cdb-4b07-b39e-4c29856309aa")
+                
.contentType(MediaType.APPLICATION_JSON).content(JsonUtil.writeValueAsString(request))
+                .accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_JSON)))
+                .andExpect(MockMvcResultMatchers.status().isOk());
+    }
 }
diff --git 
a/src/data-loading-server/src/test/java/org/apache/kylin/rest/controller/open/OpenSegmentControllerTest.java
 
b/src/data-loading-server/src/test/java/org/apache/kylin/rest/controller/open/OpenSegmentControllerTest.java
index 32bfdca1d4..8a1de250ff 100644
--- 
a/src/data-loading-server/src/test/java/org/apache/kylin/rest/controller/open/OpenSegmentControllerTest.java
+++ 
b/src/data-loading-server/src/test/java/org/apache/kylin/rest/controller/open/OpenSegmentControllerTest.java
@@ -22,6 +22,8 @@ import static 
org.apache.kylin.common.constant.HttpConstant.HTTP_VND_APACHE_KYLI
 import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.MODEL_NAME_NOT_EXIST;
 import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.PROJECT_MULTI_PARTITION_DISABLE;
 import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.SEGMENT_CONFLICT_PARAMETER;
+import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.SEGMENT_INDEX_CONFLICT_PARAMETER;
+import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.SEGMENT_INDEX_STATUS_INVALID;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -33,8 +35,10 @@ import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 
 import org.apache.kylin.common.KylinConfig;
 import org.apache.kylin.common.KylinConfigExt;
@@ -44,6 +48,7 @@ import org.apache.kylin.common.util.JsonUtil;
 import org.apache.kylin.common.util.NLocalFileMetadataTestCase;
 import org.apache.kylin.common.util.Pair;
 import org.apache.kylin.common.util.RandomUtil;
+import org.apache.kylin.metadata.cube.model.IndexEntity;
 import org.apache.kylin.metadata.model.NDataModel;
 import org.apache.kylin.metadata.model.NDataModelManager;
 import org.apache.kylin.metadata.model.Segments;
@@ -64,8 +69,11 @@ import org.apache.kylin.rest.response.IndexResponse;
 import org.apache.kylin.rest.response.NDataModelResponse;
 import org.apache.kylin.rest.response.NDataSegmentResponse;
 import org.apache.kylin.rest.response.SegmentPartitionResponse;
+import org.apache.kylin.rest.service.FusionIndexService;
 import org.apache.kylin.rest.service.FusionModelService;
 import org.apache.kylin.rest.service.ModelService;
+import org.apache.kylin.rest.service.params.IndexPlanParams;
+import org.apache.kylin.rest.service.params.PaginationParams;
 import org.apache.kylin.rest.util.AclEvaluate;
 import org.junit.After;
 import org.junit.Assert;
@@ -92,6 +100,9 @@ import 
org.springframework.test.web.servlet.setup.MockMvcBuilders;
 import org.apache.kylin.guava30.shaded.common.collect.Lists;
 import org.apache.kylin.guava30.shaded.common.collect.Maps;
 
+import shaded.parquet.com.fasterxml.jackson.core.JsonProcessingException;
+import shaded.parquet.com.fasterxml.jackson.databind.ObjectMapper;
+
 @RunWith(MockitoJUnitRunner.class)
 public class OpenSegmentControllerTest extends NLocalFileMetadataTestCase {
 
@@ -109,11 +120,16 @@ public class OpenSegmentControllerTest extends 
NLocalFileMetadataTestCase {
     @Mock
     private AclEvaluate aclEvaluate;
 
+    @Mock
+    private FusionIndexService fusionIndexService;
+
     @InjectMocks
     private final OpenSegmentController openSegmentController = 
Mockito.spy(new OpenSegmentController());
 
     private final Authentication authentication = new 
TestingAuthenticationToken("ADMIN", "ADMIN", Constant.ROLE_ADMIN);
 
+    private ObjectMapper objectMapper = new ObjectMapper();
+
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
@@ -285,7 +301,7 @@ public class OpenSegmentControllerTest extends 
NLocalFileMetadataTestCase {
                 
.accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V4_PUBLIC_JSON)))
                 .andExpect(MockMvcResultMatchers.status().isOk());
         Mockito.verify(openSegmentController).completeSegments(modelName, 
project, false, ids, null, null, false, 3,
-                null, null);
+                null, null, null);
         
mockMvc.perform(MockMvcRequestBuilders.post("/api/models/{model_name}/segments/completion",
 modelName)
                 .param("project", "default") //
                 .param("parallel", "false") //
@@ -294,7 +310,7 @@ public class OpenSegmentControllerTest extends 
NLocalFileMetadataTestCase {
                 .param("priority", 
"0").accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V4_PUBLIC_JSON)))
                 .andExpect(MockMvcResultMatchers.status().isOk());
         Mockito.verify(openSegmentController).completeSegments(modelName, 
project, false, ids, null, null, false, 0,
-                null, null);
+                null, null, null);
     }
 
     @Test
@@ -323,7 +339,7 @@ public class OpenSegmentControllerTest extends 
NLocalFileMetadataTestCase {
                 
.accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V4_PUBLIC_JSON)))
                 .andExpect(MockMvcResultMatchers.status().isOk());
         Mockito.verify(openSegmentController).completeSegments(modelName, 
project, false, ids, null, batchIndexIds,
-                true, 3, null, null);
+                true, 3, null, null, null);
     }
 
     @Test
@@ -372,6 +388,86 @@ public class OpenSegmentControllerTest extends 
NLocalFileMetadataTestCase {
         
Assert.assertTrue(contentAsString.contains(SEGMENT_CONFLICT_PARAMETER.getMsg()));
     }
 
+    @Test
+    public void testCompleteSegmentsByIndexStatus() throws Exception {
+        String modelName = "default_model_name";
+        String modelId = "89af4ee2-2cdb-4b07-b39e-4c29856309aa";
+        String project = "default";
+        String[] ids = { "ef5e0663-feba-4ed2-b71c-21958122bbff" };
+        Pair<String, String[]> pair = new Pair<>(modelId, ids);
+        IndexesToSegmentsRequest req = new IndexesToSegmentsRequest();
+        req.setProject(project);
+        req.setParallelBuildBySegment(false);
+        req.setSegmentIds(Lists.newArrayList(ids));
+        mockGetModelName(modelName, project, modelId);
+        lenient().doReturn(new EnvelopeResponse<>(KylinException.CODE_SUCCESS, 
"", "")).when(nModelController)
+                .addIndexesToSegments(modelId, req);
+        
Mockito.doReturn(pair).when(fusionModelService).convertSegmentIdWithName(modelId,
 project, ids, null);
+        MvcResult result = mockMvc
+                
.perform(MockMvcRequestBuilders.post("/api/models/{model_name}/segments/completion",
 modelName)
+                        .param("project", "default") //
+                        .param("parallel", "false") //
+                        .param("ids", ids) //
+                        .param("names", (String) null) //
+                        .param("batch_index_ids", "1,2") //
+                        .param("index_status", "NO_BUILD")
+                        
.accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V4_PUBLIC_JSON)))
+                
.andExpect(MockMvcResultMatchers.status().isInternalServerError()).andReturn();
+        String contentAsString = result.getResponse().getContentAsString();
+        
Assert.assertTrue(contentAsString.contains(SEGMENT_INDEX_CONFLICT_PARAMETER.getMsg()));
+
+        MvcResult result1 = mockMvc.perform(MockMvcRequestBuilders
+                .post("/api/models/{model_name}/segments/completion", 
modelName).param("project", "default") //
+                .param("parallel", "false") //
+                .param("ids", ids) //
+                .param("names", (String) null) //
+                .param("index_status", 
"LOCKED").accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V4_PUBLIC_JSON)))
+                
.andExpect(MockMvcResultMatchers.status().isInternalServerError()).andReturn();
+        String content1 = result1.getResponse().getContentAsString();
+        
Assert.assertTrue(content1.contains(SEGMENT_INDEX_STATUS_INVALID.getMsg()));
+
+        IndexPlanParams indexPlanParams = new IndexPlanParams(project, 
modelId, null, null, Collections.emptyList(),
+                Collections.singletonList(IndexEntity.Status.NO_BUILD), null);
+        PaginationParams paginationParams = new PaginationParams(null, null, 
null, false);
+        List<IndexResponse> emptyIndex = new ArrayList<>();
+        
Mockito.doReturn(emptyIndex).when(fusionIndexService).getIndexes(indexPlanParams,
 paginationParams, null);
+        MvcResult result2 = mockMvc
+                
.perform(MockMvcRequestBuilders.post("/api/models/{model_name}/segments/completion",
 modelName)
+                        .param("project", "default") //
+                        .param("parallel", "false") //
+                        .param("ids", ids) //
+                        .param("names", (String) null) //
+                        .param("index_status", "NO_BUILD")
+                        
.accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V4_PUBLIC_JSON)))
+                .andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
+        String content2 = result2.getResponse().getContentAsString();
+        Assert.assertNull(getJobId(content2));
+
+        List<IndexResponse> indexResponseList = new ArrayList<>();
+        IndexResponse indexResponse = new IndexResponse();
+        indexResponse.setId(1L);
+        indexResponseList.add(indexResponse);
+        
Mockito.doReturn(indexResponseList).when(fusionIndexService).getIndexes(indexPlanParams,
 paginationParams,
+                null);
+        
mockMvc.perform(MockMvcRequestBuilders.post("/api/models/{model_name}/segments/completion",
 modelName)
+                .param("project", "default") //
+                .param("parallel", "false") //
+                .param("ids", ids) //
+                .param("names", (String) null) //
+                .param("index_status", "NO_BUILD")
+                
.accept(MediaType.parseMediaType(HTTP_VND_APACHE_KYLIN_V4_PUBLIC_JSON)))
+                .andExpect(MockMvcResultMatchers.status().isOk());
+    }
+
+    @SuppressWarnings("unchecked")
+    private String getJobId(String content) throws JsonProcessingException {
+        LinkedHashMap<String, Object> envelopeResponse = 
objectMapper.readValue(content, LinkedHashMap.class);
+        Map<String, Object> data = (Map<String, Object>) 
envelopeResponse.get("data");
+        List<?> list = (List<?>) data.get("jobs");
+        Map<String, String> map = (Map<String, String>) list.get(0);
+        return map.get("job_id");
+    }
+
     @Test
     public void testDeleteSegmentsAll() throws Exception {
         String modelName = "default_model_name";

Reply via email to