ReverseE57ServiceImpl.java 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. package com.fdkankan.modeling.service.impl;
  2. import cn.hutool.core.util.StrUtil;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.fdkankan.common.constant.CommonStatus;
  5. import com.fdkankan.common.constant.ModelingBuildStatus;
  6. import com.fdkankan.common.util.FileUtils;
  7. import com.fdkankan.model.enums.ModelTypeEnums;
  8. import com.fdkankan.model.utils.ComputerUtil;
  9. import com.fdkankan.modeling.bean.BuildSceneResultBean;
  10. import com.fdkankan.modeling.constants.SysConstants;
  11. import com.fdkankan.modeling.entity.BuildLog;
  12. import com.fdkankan.modeling.exception.BuildException;
  13. import com.fdkankan.modeling.service.IBuildLogService;
  14. import com.fdkankan.modeling.service.IReverseE57Service;
  15. import com.fdkankan.rabbitmq.bean.BuildSceneCallMessage;
  16. import com.fdkankan.rabbitmq.bean.BuildSceneProcessLogMessage;
  17. import com.fdkankan.rabbitmq.bean.BuildSceneResultMqMessage;
  18. import com.fdkankan.rabbitmq.util.RabbitMqProducer;
  19. import lombok.extern.slf4j.Slf4j;
  20. import org.apache.commons.lang3.StringUtils;
  21. import org.apache.commons.lang3.time.StopWatch;
  22. import org.springframework.beans.factory.annotation.Autowired;
  23. import org.springframework.beans.factory.annotation.Value;
  24. import org.springframework.stereotype.Service;
  25. import org.springframework.util.ObjectUtils;
  26. import javax.annotation.Resource;
  27. import javax.print.DocFlavor;
  28. import java.io.File;
  29. import java.util.Date;
  30. import java.util.HashMap;
  31. import java.util.Map;
  32. import java.util.Objects;
  33. import java.util.concurrent.Future;
  34. import java.util.concurrent.TimeUnit;
  35. import java.util.concurrent.TimeoutException;
  36. @Slf4j
  37. @Service
  38. public class ReverseE57ServiceImpl implements IReverseE57Service {
  39. @Value("${queue.modeling.modeling-call}")
  40. private String queueModelingCall;
  41. @Value("${queue.modeling.modeling-process-log}")
  42. private String queueModelingProcessLog;
  43. @Value("${queue.modeling.modeling-post}")
  44. private String queueModelingPost;
  45. @Autowired
  46. private IBuildLogService buildLogService;
  47. @Resource
  48. private RabbitMqProducer rabbitMqProducer;
  49. @Value("${model.type:#{null}}")
  50. private String modelType;
  51. @Override
  52. public void build(BuildSceneCallMessage message, BuildLog buildLog) {
  53. //开始计时
  54. StopWatch watch = new StopWatch();
  55. watch.start();
  56. //发送记录计算状态为计算中
  57. rabbitMqProducer.sendByWorkQueue(queueModelingProcessLog,
  58. BuildSceneProcessLogMessage.builder().num(message.getSceneNum()).buildStatus(ModelingBuildStatus.CALCULATING.code()).queueName(queueModelingCall).build());
  59. final BuildSceneResultBean buildSceneResult = new BuildSceneResultBean();
  60. String resultQueueName = StrUtil.isNotBlank(message.getResultReceiverMqName()) ?
  61. message.getResultReceiverMqName() : queueModelingPost;
  62. buildSceneResult.setResultQueueName(resultQueueName);
  63. ModelingBuildStatus status = null;
  64. Future<ModelingBuildStatus> future = null;
  65. try {
  66. Map<String,Object> buildContext = new HashMap<>();
  67. buildContext.put("num", message.getSceneNum());
  68. buildLog.setHostName(SysConstants.hostName);
  69. buildLog.setQueueName(queueModelingCall);
  70. buildLog.setSceneNum(message.getSceneNum());
  71. buildLog.setDataSource(message.getPath());
  72. buildLog.setCreateTime(new Date());
  73. buildLog.setUpdateTime(new Date());
  74. buildLog.setBuildType(0);
  75. buildLog.setStatus(0);
  76. buildLogService.save(buildLog);
  77. future = SysConstants.executorService.submit(() -> {
  78. try {
  79. return buildScene(buildContext,message, buildSceneResult,buildLog);
  80. } catch (Exception e) {
  81. log.error("服务实例:{} 构建异常:", SysConstants.hostName, e);
  82. e.printStackTrace();
  83. return ModelingBuildStatus.FAILED;
  84. }
  85. });
  86. status = future.get(SysConstants.modelTimeOut, TimeUnit.HOURS);
  87. //结束计时
  88. watch.stop();
  89. buildLog.setDuration(watch.getTime(TimeUnit.SECONDS));
  90. } catch (TimeoutException ex) {
  91. log.error("服务实例:{} 构建异常:",SysConstants.hostName,ex);
  92. status = ModelingBuildStatus.OVERTIME;
  93. log.info("释放线程");
  94. //场景计算超时,需要中断当前执行任务,释放线程池中的任务线程,否则下个场景计算获取不到线程进行计算
  95. future.cancel(true);
  96. } catch (BuildException e){
  97. status = e.getBuildStatus();
  98. } catch(Exception e) {
  99. log.error("服务实例:{} 构建异常:", SysConstants.hostName, e);
  100. if (e.getCause() instanceof BuildException) {
  101. status = ((BuildException) e.getCause()).getBuildStatus();
  102. buildLog.setStatus(((BuildException) e.getCause()).getBuildStatus().code());
  103. } else {
  104. status = ModelingBuildStatus.FAILED;
  105. }
  106. }
  107. buildLog.setStatus(status.code());
  108. buildSceneResult.setCameraType(message.getCameraType());
  109. buildSceneResult.setBuildStatus(status);
  110. //计算后处理
  111. ModelingBuildStatus buildStatus = null;
  112. try {
  113. buildStatus = buildSceneResult.getBuildStatus();
  114. log.info("服务{} 计算结束:{},计算状态:{}", SysConstants.hostName, buildLog.getSceneNum(),buildStatus.message());
  115. buildLog.setUpdateTime(new Date());
  116. buildLog.setResultQuequeName(buildSceneResult.getResultQueueName());
  117. buildLogService.updateById(buildLog);
  118. } catch (Exception e) {
  119. log.error("计算后业务处理出错!", e);
  120. }finally {
  121. buildSceneResult.setDuration(buildLog.getDuration());
  122. this.sendCallResult(message, buildSceneResult);
  123. rabbitMqProducer.sendByWorkQueue(queueModelingProcessLog,
  124. BuildSceneProcessLogMessage.builder().num(message.getSceneNum()).buildStatus(buildStatus.code()).queueName(queueModelingCall).build());
  125. }
  126. }
  127. /**
  128. * 发送计算结果
  129. * @param message
  130. * @param buildSceneResult
  131. */
  132. private void sendCallResult(BuildSceneCallMessage message, BuildSceneResultBean buildSceneResult){
  133. ModelingBuildStatus buildStatus = buildSceneResult.getBuildStatus();
  134. //重复计算不需要发送mq做后置处理
  135. if(buildStatus.equals(ModelingBuildStatus.REPEAT)){
  136. return;
  137. }
  138. BuildSceneResultMqMessage buildResult = BuildSceneResultMqMessage.builder()
  139. .buildSuccess(buildStatus.equals(ModelingBuildStatus.SUCCESS))
  140. .computeTime(buildSceneResult.getDuration())
  141. .path(buildSceneResult.getPath())
  142. .hostName(SysConstants.hostName)
  143. .build();
  144. buildResult.setBuildContext(message.getBuildContext());
  145. rabbitMqProducer.sendByWorkQueue(buildSceneResult.getResultQueueName(),buildResult);
  146. }
  147. private ModelingBuildStatus buildScene(Map<String,Object> buildContext,BuildSceneCallMessage message, BuildSceneResultBean buildSceneResult,BuildLog logRecord) throws Exception{
  148. //如果mq生产者在消息体中设置了结算结果mq队列名,就发到这个队列,否则就发送到默认队列
  149. String path = message.getPath();
  150. String num = message.getSceneNum();
  151. //不同的相机不同的方法
  152. String cameraType = message.getCameraType();
  153. //0表示有4k图,1表示没有
  154. //判断调用V2还是V3版本的算法
  155. String buildType = ObjectUtils.isEmpty(message.getBuildType()) ? "V2" : message.getBuildType();
  156. buildSceneResult.setCameraType(cameraType);
  157. buildSceneResult.setNum(num);
  158. buildSceneResult.setPath(path);
  159. String splitType = "SPLIT_V29";
  160. String skyboxType = "SKYBOX_V11";
  161. String otherType = (String)message.getExt().get("otherType");
  162. Integer isObj = (Integer) message.getExt().get("isObj");
  163. if(StrUtil.isNotEmpty(modelType) && ModelTypeEnums.TILE_CODE.equals(modelType)){
  164. skyboxType = "SKYBOX_V15";
  165. }
  166. if(Objects.nonNull(isObj) && isObj == CommonStatus.YES.code().intValue()){
  167. splitType = "SPLIT_V30";
  168. }
  169. this.createProjectAndDataFile(path,num, splitType, skyboxType,otherType,null,null);
  170. //计算模型并返回需要上传oss的文件集合
  171. ComputerUtil.computer(num, path, buildType);
  172. // 检测计算结果文件是否有生成
  173. String resultsPath = path + File.separator + "results" + File.separator;
  174. if (!new File(resultsPath + "upload.json").exists()) {
  175. log.error("未检测到计算结果文件:upload.json");
  176. return ModelingBuildStatus.FAILED;
  177. }
  178. log.info("八目上完oss结束修改数据:"+num);
  179. return ModelingBuildStatus.SUCCESS;
  180. }
  181. public void createProjectAndDataFile(String path, String sceneNum, String splitType, String skyboxType, String otherType, Map<String, Object> projectExtras, Map<String, Object> dataExtras) {
  182. JSONObject projectJson = new JSONObject();
  183. if (!org.apache.commons.lang3.ObjectUtils.isEmpty(projectExtras)) {
  184. projectJson.putAll(projectExtras);
  185. }
  186. projectJson.put("sceneNum", sceneNum);
  187. FileUtils.writeFile(path + File.separator + "project.json", projectJson.toString());
  188. JSONObject dataJson = new JSONObject();
  189. if (!org.apache.commons.lang3.ObjectUtils.isEmpty(dataExtras)) {
  190. dataJson.putAll(dataExtras);
  191. }
  192. dataJson.put("split_type", splitType);
  193. dataJson.put("skybox_type", skyboxType);
  194. dataJson.put("extras", (Object)null);
  195. dataJson.put("other_type", otherType);
  196. FileUtils.writeFile(path + File.separator + "data.json", dataJson.toString());
  197. }
  198. }