夜得朦胧 9 tháng trước cách đây
mục cha
commit
5ecdb9fa85
11 tập tin đã thay đổi với 219 bổ sung11 xóa
  1. 2 0
      api-common/src/main/java/api/common/pojo/param/project/MultiSimulationProjectKafkaParam.java
  2. 1 0
      api-common/src/main/java/api/common/pojo/param/project/MultiSimulationSceneParam.java
  3. 53 8
      simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/app/service/ProjectApplicationService.java
  4. 39 2
      simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/app/service/TaskApplicationService.java
  5. 12 1
      simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/domain/service/ProjectDomainService.java
  6. 15 0
      simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/domain/service/TaskDomainService.java
  7. 3 0
      simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/infra/db/mysql/mapper/MultiSimulationProjectResultMapper.java
  8. 7 0
      simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/infra/db/mysql/mapper/MultiSimulationProjectTaskRecordMapper.java
  9. 5 0
      simulation-resource-server/src/main/java/com/css/simulation/resource/server/adapter/controller/job_manage/JobManageController.java
  10. 80 0
      simulation-resource-server/src/main/java/com/css/simulation/resource/server/app/impl/MultiSimulationProjectServiceImpl.java
  11. 2 0
      simulation-resource-server/src/main/java/com/css/simulation/resource/server/app/service/job_manage/MultiSimulationProjectService.java

+ 2 - 0
api-common/src/main/java/api/common/pojo/param/project/MultiSimulationProjectKafkaParam.java

@@ -18,5 +18,7 @@ public class MultiSimulationProjectKafkaParam {
     private String simulationMageGroupId;
 
     private Integer defaultTime;
+
+    private Boolean isAll;
     private List<MultiSimulationSceneKafkaParam> kafkaParamList;
 }

+ 1 - 0
api-common/src/main/java/api/common/pojo/param/project/MultiSimulationSceneParam.java

@@ -22,6 +22,7 @@ public class MultiSimulationSceneParam {
 
     /**
      * 复制场景时使用
+     * 再次执行单个场景任务时也使用
      */
     private List<String> sceneIdList;
 

+ 53 - 8
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/app/service/ProjectApplicationService.java

@@ -1144,13 +1144,6 @@ public class ProjectApplicationService {
         //* -------------------------------- 0 读取消息,创建临时目录 --------------------------------
         String projectId = projectStartMessageEntity.getProjectId();                // 手动执行项目 id 或 自动执行子项目 id
         try {
-            // 首先删掉历史的projectId记录
-            taskRecordMapper.deleteProjectByProjectId(projectId);
-            resultMapper.deleteProjectResultByProjectId(projectId);
-            KafkaUtil.deleteTopic(kafkaAdminClient, projectId);
-
-            List<MultiSimulationSceneKafkaParam> kafkaParamList = projectStartMessageEntity.getKafkaParamList();
-
             MultiSimulationProjectVO projectVO = multiSimulationProjectMapper.selectMultiSimulationProjectById(projectId);
             if (Objects.isNull(projectVO)) {
                 throw new RuntimeException("未找到有效的仿真任务");
@@ -1160,6 +1153,56 @@ public class ProjectApplicationService {
             if (Objects.isNull(groupPO) || StringUtils.isBlank(groupPO.getControllerPath()) || StringUtils.isBlank(groupPO.getConnectorPath())) {
                 throw new RuntimeException("仿真镜像组无效");
             }
+
+            // 首先删掉历史的projectId记录
+            if (projectStartMessageEntity.getIsAll() == null || projectStartMessageEntity.getIsAll()){
+                taskRecordMapper.deleteProjectByProjectId(projectId);
+                resultMapper.deleteProjectResultByProjectId(projectId);
+                KafkaUtil.deleteTopic(kafkaAdminClient, projectId);
+            }else {
+                List<MultiSimulationSceneKafkaParam> kafkaParamList = projectStartMessageEntity.getKafkaParamList();
+                List<MultiTaskMessageEntity> entityList = new ArrayList<>();
+                for (MultiSimulationSceneKafkaParam param: kafkaParamList) {
+                    String sceneId = param.getId();
+                    taskRecordMapper.updateMultiSimulationProjectTaskRecordStatusBySceneId(MultiSimulationStatusEnum.INIT_STATUS.getProjectStatus(), sceneId, 0);
+                    resultMapper.deleteProjectResultBySceneId(sceneId);
+                    MultiSimulationProjectTaskRecordPO taskRecordPO = taskRecordMapper.selectMultiSimulationProjectTaskRecordBySceneId(sceneId);
+                    if (!Objects.isNull(taskRecordPO)){
+                        String taskBody = taskRecordPO.getTaskBody();
+                        MultiTaskMessageEntity messageEntity = JsonUtil.jsonToBean(taskBody, MultiTaskMessageEntity.class);
+                        entityList.add(messageEntity);
+
+                        List<MultiSimulationSceneCarVO> simulationSceneCarVOList = param.getSimulationSceneCarVOList();
+                        if (CollectionUtils.isEmpty(simulationSceneCarVOList)) {
+                            throw new RuntimeException("未配置车辆");
+                        }
+                        for (MultiSimulationSceneCarVO sceneCar : simulationSceneCarVOList) {
+                            String sceneCarId = sceneCar.getId();
+                            // 处理算法id
+                            String algorithmId = sceneCar.getAlgorithmId();
+                            log.info("项目:" + projectId + ",场景:" + sceneId + ",车辆id:" + sceneCarId + ",开始算法导入。");
+                            String algorithmDockerImage = handleAlgorithm(sceneId, algorithmId);
+                            log.info("项目:" + projectId + ",场景:" + sceneId + ",车辆id:" + sceneCarId + ",算法已导入" + algorithmDockerImage);
+                            customRedisClient.set(projectDomainService.getMultiAlgorithmIdRedisKey(algorithmId, projectId), algorithmDockerImage);
+                        }
+                    }
+                }
+                KafkaUtil.deleteTopic(kafkaAdminClient, projectId);
+                MultiProjectWaitQueueEntity build = MultiProjectWaitQueueEntity.builder()
+                    .multiTaskMessageEntityList(entityList)
+                    .projectId(projectId)
+                    .connectorPath(groupPO.getConnectorPath())
+                    .controllerPath(groupPO.getControllerPath())
+                    .softwarePath(groupPO.getSoftwarePath())
+                    .waitingParallelism(entityList.size())
+                    .kafkaParamList(kafkaParamList)
+                    .runState(-1)
+                    .build();
+                log.info("MultiProjectWaitQueueEntity返回结果:{}", JSONObject.toJSONString(build));
+                return build;
+            }
+
+            List<MultiSimulationSceneKafkaParam> kafkaParamList = projectStartMessageEntity.getKafkaParamList();
             List<MultiTaskMessageEntity> entityList = new ArrayList<>();
             for (MultiSimulationSceneKafkaParam kafkaParam : kafkaParamList) {
                 String taskId = StringUtil.getRandomUUID();
@@ -1255,8 +1298,10 @@ public class ProjectApplicationService {
             }
             int sort = 0;
             for (MultiTaskMessageEntity entity : entityList) {
+//                int i = taskRecordMapper.addMultiSimulationProjectTaskRecord(entity.getInfo().getTask_id(), entity.getInfo().getScene_id(), entity.getInfo().getProject_id(),
+//                        JSONObject.toJSONString(entity), sort);
                 int i = taskRecordMapper.addMultiSimulationProjectTaskRecord(entity.getInfo().getTask_id(), entity.getInfo().getScene_id(), entity.getInfo().getProject_id(),
-                        JSONObject.toJSONString(entity), sort);
+                    JsonUtil.beanToJson(entity), sort);
                 sort++;
             }
             log.info("project:{},共插入{}条数据", projectId, entityList.size());

+ 39 - 2
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/app/service/TaskApplicationService.java

@@ -33,8 +33,11 @@ import io.minio.http.Method;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.kafka.clients.admin.Admin;
+import org.apache.kafka.clients.producer.RecordMetadata;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.kafka.support.SendResult;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
@@ -73,6 +76,8 @@ public class TaskApplicationService {
     private CustomConfiguration customConfiguration;
     @Resource
     private TaskDomainService taskDomainService;
+    @Resource
+    private KafkaTemplate<String, String> kafkaTemplate;
 
     @Resource
     private MultiSimulationProjectMapper multiSimulationProjectMapper;
@@ -234,6 +239,36 @@ public class TaskApplicationService {
             log.info("多模式仿真收到不存在的任务的状态消息:" + taskId);
             return;
         }
+        try {
+            if (DictConstants.TASK_ABORTED.equals(state)){
+                // 进行三次重试
+                int multiTaskRetryTimes = taskDomainService.getMultiTaskRetryTimes(taskId);
+                if (multiTaskRetryTimes < 3){
+                    String taskBody = taskEntity.getTaskBody();
+                    SendResult<String, String> stringStringSendResult = kafkaTemplate.send(taskEntity.getProjectId(), 0,
+                        taskId, taskBody).get();
+                    RecordMetadata recordMetadata = stringStringSendResult.getRecordMetadata();
+                    String topic = recordMetadata.topic();  // 消息发送到的topic
+                    int partition = recordMetadata.partition(); // 消息发送到的分区
+                    long offset = recordMetadata.offset();  // 消息在分区内的offset
+                    log.info("多模式仿真任务发送消息成功, 主题 topic 为项目ID:" + topic + " 分区 partition 为:" + partition + " 偏移量为:" + offset);
+                    String yamlRedisKeyCache = "multi_yaml_cache_project_" + taskEntity.getProjectId()+"_scene_" + taskEntity.getSceneId();
+                    String s = stringRedisTemplate.opsForValue().get(yamlRedisKeyCache);
+                    if (!StringUtil.isEmpty(s)){
+                        projectDomainService.createMultiPodBeginByYaml(s);
+                        taskDomainService.setMultiTaskRetryTimes(taskId, multiTaskRetryTimes + 1);
+                        return;
+                    }else {
+                        log.info("进行重试时,未找到yaml,taskId:{},projectId:{}", taskId, taskEntity.getProjectId());
+                        // 不再进行重试,执行后续流程
+                    }
+                }else {
+                    log.info("多模式仿真任务重试三次之后失败,taskId:{},projectId:{},sceneId:{}", taskId,taskEntity.getProjectId(), taskEntity.getSceneId());
+                }
+            }
+        }catch (Exception e){
+            log.info("多模式仿真任务反馈执行abort判断异常taskId:{}", taskId, e);
+        }
         String projectId = taskEntity.getProjectId(); // 项目 id
         String minioUploadPath = projectId + "/" + taskId + "/";
 
@@ -241,6 +276,7 @@ public class TaskApplicationService {
         customRedisClient.lock(lock1, 1L, 30 * 60L);
         String isChoiceGpu = DictConstants.USE_GPU;
         try {
+
             MultiSimulationProjectVO projectVO = multiSimulationProjectMapper.selectMultiSimulationProjectById(projectId);
 //            Integer status = projectVO.getProjectStatus();
             MultiSimulationProjectParam multiSimulationProjectParam = new MultiSimulationProjectParam();
@@ -388,12 +424,13 @@ public class TaskApplicationService {
                 }
             }
             if (allCom){
-                multiSimulationProjectParam.setProjectStatus(DictConstants.TASK_ABORTED.equals(state) ? MultiSimulationStatusEnum.TERMINATED_STATUS.getProjectStatus() : MultiSimulationStatusEnum.COMPLETED_STATUS.getProjectStatus());
+//                multiSimulationProjectParam.setProjectStatus(DictConstants.TASK_ABORTED.equals(state) ? MultiSimulationStatusEnum.TERMINATED_STATUS.getProjectStatus() : MultiSimulationStatusEnum.COMPLETED_STATUS.getProjectStatus());
+                multiSimulationProjectParam.setProjectStatus(MultiSimulationStatusEnum.COMPLETED_STATUS.getProjectStatus());
                 multiSimulationProjectMapper.updateMultiSimulationProjectStatus(multiSimulationProjectParam);
                 // 删除kafka topic
                 KafkaUtil.deleteTopic(kafkaAdminClient, projectId);
                 //6 删除项目 pod 启动文件
-                FileUtil.deleteFileBySubstring(multiPodYamlDirectory, projectId);
+                FileUtil.deleteFileBySubstring(multiPodYamlDirectory + "multi/", projectId);
                 //7 删除项目临时文件
                 FileUtil.rm(linuxTempPath + "multiProject/" + projectId + "/");
                 // 删除minio临时文件

+ 12 - 1
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/domain/service/ProjectDomainService.java

@@ -237,7 +237,7 @@ public class ProjectDomainService {
                                                   String nodeName, int kafkaPartition, long kafkaOffset, String isChoiceGpu) {
         String podName = getMultiRandomPodName(projectId);   // 生成 podName
         String podYaml = getMultiPodYamlName(nodeName, podName);     // 模板文件名称
-        String yamlPath = multiPodYamlDirectory + podYaml;
+        String yamlPath = multiPodYamlDirectory + "multi/" + podYaml;
         String podString = FileUtil.read(new File(multiVtdPodTemplateFirstYaml));
         String algorithmStr = FileUtil.read(new File(multiVtdPodTemplateLastYaml));
         String algorithmInitStr = FileUtil.read(new File(multiVtdPodTemplateInitYaml));
@@ -307,6 +307,9 @@ public class ProjectDomainService {
         // 保存 yaml 地址
         String yamlRedisKey = "multi_project:" + projectId+":scene:" + messageEntity.getInfo().getScene_id() + ":node:" + nodeName + ":yaml:" + podName;
         stringRedisTemplate.opsForValue().set(yamlRedisKey, yamlPath);
+        String yamlRedisKeyCache = "multi_yaml_cache_project_" + projectId+"_scene_" + messageEntity.getInfo().getScene_id();
+        stringRedisTemplate.opsForValue().set(yamlRedisKeyCache, podYaml, 24 * 60 *60 ,TimeUnit.SECONDS);
+
         MultiCreateYamlRet multiCreateYamlRet = new MultiCreateYamlRet();
         multiCreateYamlRet.setProjectId(projectId);
         multiCreateYamlRet.setSceneId(messageEntity.getInfo().getScene_id());
@@ -492,6 +495,12 @@ public class ProjectDomainService {
         new Thread(() -> KubernetesUtil.applyYaml(podYamlPath), "apply-" + podName).start();
     }
 
+    public void createMultiPodBeginByYaml(String yamlPath) {
+        String nodeName = yamlPath.split("#")[0];
+        String podName = yamlPath.split("#")[1].split("\\.")[0];
+        new Thread(() -> KubernetesUtil.applyYaml(yamlPath), "apply-" + podName).start();
+    }
+
 
     /**
      * @param redisKey yaml 地址的缓存 key
@@ -1295,8 +1304,10 @@ public class ProjectDomainService {
     public void selectProjectReportById(String projectType, String projectId) {
 //        String tokenUrl = customConfiguration.getTokenUri() + "?grant_type=client_credentials" + "&client_id=" + customConfiguration.getClientId() + "&client_secret=" + customConfiguration.getClientSecret();
         String tokenUrl = "http://10.14.85.241/simulation/oauth/client/sign/username_for_scheduler";
+//        String tokenUrl = "http://60.205.245.110:7001/simulation/oauth/client/sign/username_for_scheduler";
         Map<String, String> params1 = new HashMap<>();
         params1.put("username", "sysadmin");
+//        params1.put("username", "admin");
         params1.put("password", "123456");
         String response = HttpUtil.post(tokenUrl, null, params1);
         log.info("获取仿真云平台 token:" + tokenUrl + ",结果为:" + response);

+ 15 - 0
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/domain/service/TaskDomainService.java

@@ -340,6 +340,21 @@ public class TaskDomainService {
         ThreadPool.sceneEvaluationComputePool.execute(new SceneEvaluationComputeRunnable(sceneEvaluationComputeParam));
     }
 
+    public int getMultiTaskRetryTimes(String taskId){
+        String keyRetryTimes = "multi_task_retry_times_" + taskId;
+        String s = stringRedisTemplate.opsForValue().get(keyRetryTimes);
+        if (StringUtil.isEmpty(s)){
+            return 0;
+        }else {
+            return Integer.valueOf(s);
+        }
+    }
+
+    public void setMultiTaskRetryTimes(String taskId, int times){
+        String keyRetryTimes = "multi_task_retry_times_" + taskId;
+        stringRedisTemplate.opsForValue().set(keyRetryTimes, String.valueOf(times), 24 * 60 * 60, TimeUnit.SECONDS);
+    }
+
     public void computeFirst(List<LeafIndexEntity> leafIndexList, List<IndexTemplateEntity> allIndexTemplateList, String projectId, int maxLevel) {
         log.debug("计算父指标得分:" + leafIndexList);
         Iterator<LeafIndexEntity> leafTaskIndexIterator = leafIndexList.iterator();

+ 3 - 0
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/infra/db/mysql/mapper/MultiSimulationProjectResultMapper.java

@@ -17,4 +17,7 @@ public interface MultiSimulationProjectResultMapper {
 
     @Delete("delete from multi_simulation_project_result where project_id = #{projectId}")
     int deleteProjectResultByProjectId(@Param("projectId") String projectId);
+
+    @Delete("delete from multi_simulation_project_result where scene_id = #{sceneId}")
+    int deleteProjectResultBySceneId(@Param("sceneId") String sceneId);
 }

+ 7 - 0
simulation-resource-scheduler/src/main/java/com/css/simulation/resource/scheduler/infra/db/mysql/mapper/MultiSimulationProjectTaskRecordMapper.java

@@ -28,6 +28,10 @@ public interface MultiSimulationProjectTaskRecordMapper {
         "where id = #{taskId}")
     int updateMultiSimulationProjectTaskRecordStatus(@Param("status") Integer status, @Param("taskId") String taskId, @Param("deleted") Integer deleted);
 
+    @Update("update multi_simulation_project_task_record set status = #{status},deleted = #{deleted} " +
+        "where scene_id = #{sceneId}")
+    int updateMultiSimulationProjectTaskRecordStatusBySceneId(@Param("status") Integer status, @Param("sceneId") String sceneId, @Param("deleted") Integer deleted);
+
     @Update("update multi_simulation_project_task_record set status = #{status},deleted = #{deleted},start_time = #{startTime} " +
         "where id = #{taskId}")
     int updateMultiSimulationProjectTaskRecordStatusAndStart(@Param("status") Integer status, @Param("taskId") String taskId, @Param("deleted") Integer deleted, @Param("startTime") Long startTime);
@@ -42,6 +46,9 @@ public interface MultiSimulationProjectTaskRecordMapper {
     @Select("select id,project_id as projectId,scene_id as sceneId,task_body as taskBody,status,sort,start_time as startTime,end_time as endTime from multi_simulation_project_task_record where id = #{taskId} and deleted = 0")
     MultiSimulationProjectTaskRecordPO selectMultiSimulationProjectTaskRecordById(@Param("taskId") String taskId);
 
+    @Select("select id,project_id as projectId,scene_id as sceneId,task_body as taskBody,status,sort,start_time as startTime,end_time as endTime from multi_simulation_project_task_record where scene_id = #{sceneId} and deleted = 0")
+    MultiSimulationProjectTaskRecordPO selectMultiSimulationProjectTaskRecordBySceneId(@Param("sceneId") String sceneId);
+
     @Delete("delete from multi_simulation_project_task_record where project_id = #{projectId}")
     int deleteProjectByProjectId(@Param("projectId") String projectId);
 

+ 5 - 0
simulation-resource-server/src/main/java/com/css/simulation/resource/server/adapter/controller/job_manage/JobManageController.java

@@ -359,6 +359,11 @@ public class JobManageController {
     return multiSimulationProjectService.updateMultiSimulationProjectStatus(param);
   }
 
+  @RequestMapping("/updateMultiSimulationProjectSceneStatusRetry")
+  public ResponseBodyVO updateMultiSimulationProjectSceneStatusRetry(@RequestBody MultiSimulationSceneParam param) {
+    return multiSimulationProjectService.updateMultiSimulationSceneRetry(param);
+  }
+
   @RequestMapping("/submitMultiSimulationProjectDetail")
   public ResponseBodyVO submitMultiSimulationProjectDetail(@RequestBody MultiSimulationProjectParam param) {
     return multiSimulationProjectService.submitMultiSimulationProjectDetail(param);

+ 80 - 0
simulation-resource-server/src/main/java/com/css/simulation/resource/server/app/impl/MultiSimulationProjectServiceImpl.java

@@ -234,6 +234,60 @@ public class MultiSimulationProjectServiceImpl implements MultiSimulationProject
         return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE);
     }
 
+    @Override
+    @SneakyThrows
+    public ResponseBodyVO updateMultiSimulationSceneRetry(MultiSimulationSceneParam param){
+        String projectId = param.getProjectId();
+        MultiSimulationProjectVO projectVO = multiSimulationProjectMapper.selectMultiSimulationProjectById(projectId);
+        if (Objects.isNull(projectVO)){
+            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "未查询到可用的任务");
+        }
+        String simulationMageGroupId = projectVO.getSimulationMageGroupId();
+        if (StringUtils.isBlank(simulationMageGroupId)){
+            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "仿真镜像组为空");
+        }
+        Integer projectStatus = projectVO.getProjectStatus();
+        if (projectStatus != MultiSimulationStatusEnum.COMPLETED_STATUS.getProjectStatus()){
+            return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "当前仿真任务状态不允许只执行部分场景任务");
+        }
+        List<String> sceneIdList = param.getSceneIdList();
+        Set<String> sceneSet = new HashSet<>(sceneIdList);
+        MultiSimulationSceneParam multiSimulationSceneParam = new MultiSimulationSceneParam();
+        multiSimulationSceneParam.setProjectId(projectId);
+        List<MultiSimulationSceneVO> sceneVOList = simulationSceneMapper.selectSceneList(multiSimulationSceneParam);
+        List<MultiSimulationSceneVO> multiSimulationSceneVOS = new ArrayList<>();
+        if (!CollectionUtils.isEmpty(sceneVOList)){
+            for (MultiSimulationSceneVO vo: sceneVOList) {
+                if (sceneSet.contains(vo.getId())){
+                    multiSimulationSceneVOS.add(vo);
+                }
+            }
+        }
+        ResponseBodyVO responseBodyVO = checkAllScene(multiSimulationSceneVOS);
+        if (responseBodyVO.getCode() != ResponseBodyVO.Response.SUCCESS.getCode()){
+            return responseBodyVO;
+        }
+        for (MultiSimulationSceneVO sceneVo: multiSimulationSceneVOS) {
+            String sceneVoId = sceneVo.getId();
+            String mapId = sceneVo.getMapId();
+            SimulationMapVO simulationMapVO = mapMapper.selectMapByMapId(mapId);
+            if (Objects.isNull(simulationMapVO)){
+                return new ResponseBodyVO<>(ResponseBodyVO.Response.CLIENT_FAILURE, "场景id:" + sceneVoId + "未查到有效的地图");
+            }
+            MultiSimulationSceneCarParam sceneCarParam = new MultiSimulationSceneCarParam();
+            sceneCarParam.setSceneId(sceneVoId);
+            sceneCarParam.setMapId(mapId);
+            List<MultiSimulationSceneCarVO> multiSimulationSceneCarVOS = sceneCarMapper.selectSceneCarList(sceneCarParam);
+            ResponseBodyVO sceneCars = checkAllSceneCars(multiSimulationSceneCarVOS, sceneVoId);
+            if (sceneCars.getCode() != ResponseBodyVO.Response.SUCCESS.getCode()){
+                return sceneCars;
+            }
+        }
+        MultiSimulationProjectKafkaParam multiSimulationProjectKafkaParam = buildSendKafkaParamByScene(projectId, projectVO.getProjectMaxSeconds(), simulationMageGroupId, multiSimulationSceneVOS);
+        projectRunToKafka(multiSimulationProjectKafkaParam);
+        return new ResponseBodyVO<>(ResponseBodyVO.Response.SUCCESS);
+    }
+
     public MultiSimulationProjectKafkaParam buildSendKafkaParam(String projectId, Integer defaultTime, String simulationMageGroupId){
         MultiSimulationProjectKafkaParam multiSimulationProjectKafkaParam = new MultiSimulationProjectKafkaParam();
         multiSimulationProjectKafkaParam.setProjectId(projectId);
@@ -260,6 +314,32 @@ public class MultiSimulationProjectServiceImpl implements MultiSimulationProject
         return multiSimulationProjectKafkaParam;
     }
 
+    public MultiSimulationProjectKafkaParam buildSendKafkaParamByScene(String projectId, Integer defaultTime, String simulationMageGroupId, List<MultiSimulationSceneVO> multiSimulationSceneVOS){
+        MultiSimulationProjectKafkaParam multiSimulationProjectKafkaParam = new MultiSimulationProjectKafkaParam();
+        multiSimulationProjectKafkaParam.setProjectId(projectId);
+        multiSimulationProjectKafkaParam.setSimulationMageGroupId(simulationMageGroupId);
+        multiSimulationProjectKafkaParam.setIsAll(false);
+        MultiSimulationSceneParam sceneParam = new MultiSimulationSceneParam();
+        sceneParam.setProjectId(projectId);
+        List<MultiSimulationSceneKafkaParam> sceneKafkaParamList = new ArrayList<>();
+        for (MultiSimulationSceneVO scene : multiSimulationSceneVOS) {
+            String id = scene.getId();
+            MultiSimulationSceneKafkaParam multiSimulationSceneKafkaParam = new MultiSimulationSceneKafkaParam();
+            multiSimulationSceneKafkaParam.setMapId(scene.getMapId());
+            multiSimulationSceneKafkaParam.setProjectId(scene.getProjectId());
+            // 设置场景id
+            multiSimulationSceneKafkaParam.setId(id);
+            MultiSimulationSceneCarParam sceneCarParam = new MultiSimulationSceneCarParam();
+            sceneCarParam.setSceneId(id);
+            List<MultiSimulationSceneCarVO> multiSimulationSceneCarVOS = sceneCarMapper.selectSceneCarList(sceneCarParam);
+            multiSimulationSceneKafkaParam.setSimulationSceneCarVOList(multiSimulationSceneCarVOS);
+            sceneKafkaParamList.add(multiSimulationSceneKafkaParam);
+        }
+        multiSimulationProjectKafkaParam.setKafkaParamList(sceneKafkaParamList);
+        multiSimulationProjectKafkaParam.setDefaultTime(defaultTime);
+        return multiSimulationProjectKafkaParam;
+    }
+
     @SneakyThrows
     private void projectRunToKafka(MultiSimulationProjectKafkaParam param) {
         KafkaParameter kafkaParameter = new KafkaParameter();

+ 2 - 0
simulation-resource-server/src/main/java/com/css/simulation/resource/server/app/service/job_manage/MultiSimulationProjectService.java

@@ -16,6 +16,8 @@ public interface MultiSimulationProjectService {
 
     ResponseBodyVO updateMultiSimulationProjectStatus(MultiSimulationProjectParam param);
 
+    ResponseBodyVO updateMultiSimulationSceneRetry(MultiSimulationSceneParam param);
+
     ResponseBodyVO submitMultiSimulationProjectDetail(MultiSimulationProjectParam param);
 
     ResponseBodyVO<String> updateMultiSimulationProject(MultiSimulationProjectParam param);