CutModelServiceImpl.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. package com.fdkankan.scene.service.impl;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.io.FileUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.alibaba.fastjson.JSON;
  6. import com.alibaba.fastjson.JSONArray;
  7. import com.alibaba.fastjson.JSONObject;
  8. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  9. import com.fdkankan.common.constant.CommonStatus;
  10. import com.fdkankan.common.constant.ErrorCode;
  11. import com.fdkankan.common.constant.FileBizType;
  12. import com.fdkankan.common.exception.BusinessException;
  13. import com.fdkankan.common.util.FileUtils;
  14. import com.fdkankan.fyun.face.FYunFileServiceInterface;
  15. import com.fdkankan.model.constants.ConstantFilePath;
  16. import com.fdkankan.model.constants.UploadFilePath;
  17. import com.fdkankan.redis.constant.RedisKey;
  18. import com.fdkankan.redis.constant.RedisLockKey;
  19. import com.fdkankan.redis.util.RedisLockUtil;
  20. import com.fdkankan.redis.util.RedisUtil;
  21. import com.fdkankan.scene.bean.TagBean;
  22. import com.fdkankan.scene.entity.SceneEditInfoExt;
  23. import com.fdkankan.scene.entity.ScenePlus;
  24. import com.fdkankan.scene.entity.ScenePlusExt;
  25. import com.fdkankan.scene.service.*;
  26. import com.fdkankan.scene.vo.BaseJsonArrayParamVO;
  27. import com.fdkankan.scene.vo.BaseSceneParamVO;
  28. import com.fdkankan.scene.vo.DeleteFileParamVO;
  29. import com.fdkankan.scene.vo.DeleteSidListParamVO;
  30. import com.fdkankan.web.response.ResultData;
  31. import com.google.j2objc.annotations.AutoreleasePool;
  32. import org.springframework.beans.factory.annotation.Autowired;
  33. import org.springframework.stereotype.Service;
  34. import java.io.IOException;
  35. import java.util.*;
  36. import java.util.stream.Collectors;
  37. @Service
  38. public class CutModelServiceImpl implements ICutModelService {
  39. private final String CUT_MODEL_JSON_NAME = "cutModel.json";
  40. @Autowired
  41. private IScenePlusService scenePlusService;
  42. @Autowired
  43. private IScenePlusExtService scenePlusExtService;
  44. @Autowired
  45. private ISceneEditInfoExtService sceneEditInfoExtService;
  46. @Autowired
  47. private ISceneEditInfoService sceneEditInfoService;
  48. @Autowired
  49. private RedisUtil redisUtil;
  50. @Autowired
  51. private RedisLockUtil redisLockUtil;
  52. @Autowired
  53. private FYunFileServiceInterface fYunFileService;
  54. @Autowired
  55. private ISceneUploadService sceneUploadService;
  56. @Override
  57. public ResultData saveCutModel(BaseJsonArrayParamVO param) throws Exception {
  58. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
  59. this.addOrUpdate(param.getNum(), param.getData());
  60. //保存数据库
  61. SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
  62. this.updateDb(param.getNum(), scenePlus.getId());
  63. // this.updateById(sceneEditInfoExt);
  64. sceneEditInfoService.upgradeVersionById(sceneEditInfoExt.getEditInfoId());
  65. return ResultData.ok();
  66. }
  67. @Override
  68. public List<JSONObject> listCutModel(BaseSceneParamVO param) throws Exception {
  69. List<JSONObject> tags = new ArrayList<>();
  70. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
  71. SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
  72. this.syncFileToRedis(param.getNum());
  73. //获取裁剪模型数据
  74. String key = String.format(RedisKey.SCENE_CUT_MODEL, param.getNum());
  75. List<String> list = redisUtil.hgetValues(key);
  76. if(CollUtil.isNotEmpty(list)){
  77. List<TagBean> sortList = list.stream().map(str -> {
  78. JSONObject jsonObject = JSON.parseObject(str);
  79. TagBean tagBean = new TagBean();
  80. tagBean.setCreateTime(jsonObject.getLong("createTime"));
  81. jsonObject.remove("createTime");
  82. tagBean.setTag(jsonObject);
  83. return tagBean;
  84. }).collect(Collectors.toList());
  85. sortList.sort(Comparator.comparingLong(TagBean::getCreateTime).reversed());
  86. tags = sortList.stream().map(item -> item.getTag()).collect(Collectors.toList());
  87. }
  88. return tags;
  89. }
  90. @Override
  91. public ResultData deleteCutModel(DeleteSidListParamVO param) throws Exception {
  92. ScenePlus scenePlus = scenePlusService.getScenePlusByNum(param.getNum());
  93. ScenePlusExt scenePlusExt = scenePlusExtService.getScenePlusExtByPlusId(scenePlus.getId());
  94. String bucket = scenePlusExt.getYunFileBucket();
  95. List<String> deleteSidList = param.getSidList();
  96. this.syncFileToRedis(param.getNum());
  97. //处理删除状态数据
  98. List<String> deleteList = this.deleteCutModel(param.getNum(), deleteSidList, bucket);
  99. //写入本地文件,作为备份
  100. this.writeFile(param.getNum());
  101. //保存数据库
  102. SceneEditInfoExt sceneEditInfoExt = sceneEditInfoExtService.getByScenePlusId(scenePlus.getId());
  103. this.updateDb(param.getNum(), scenePlus.getId());
  104. sceneEditInfoService.upgradeVersionById(sceneEditInfoExt.getEditInfoId());
  105. return ResultData.ok();
  106. }
  107. @Override
  108. public void publicCutModel(String sceneNum, String bucket) throws IOException {
  109. String Key = String.format(RedisKey.SCENE_CUT_MODEL, sceneNum);
  110. String userEditPath = String.format(UploadFilePath.USER_EDIT_PATH, sceneNum) + "cutModel.json";
  111. List<String> list = redisUtil.hgetValues(Key);
  112. if(CollUtil.isEmpty(list)){
  113. fYunFileService.deleteFile(bucket, userEditPath);
  114. return;
  115. }
  116. List<JSONObject> collect = list.stream().map(str -> JSON.parseObject(str)).collect(Collectors.toList());
  117. fYunFileService.uploadFile(bucket, JSON.toJSONString(collect).getBytes(), userEditPath);
  118. }
  119. private List<String> deleteCutModel(String num, List<String> deleteSidList, String bucket) throws Exception {
  120. if(CollUtil.isEmpty(deleteSidList)){
  121. return null;
  122. }
  123. //从redis中加载热点数据
  124. String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
  125. List<String> deletDataList = redisUtil.hMultiGet(key, deleteSidList);
  126. if(CollUtil.isNotEmpty(deletDataList)){
  127. redisUtil.hdel(key, deleteSidList.toArray());
  128. }
  129. return deletDataList;
  130. }
  131. private void updateDb(String num, Long scenePlusId){
  132. //查询缓存是否包含热点数据
  133. String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
  134. Map<String, String> cutModelMap = redisUtil.hmget(key);
  135. boolean hasCutModel= false;
  136. for (Map.Entry<String, String> tagMap : cutModelMap.entrySet()) {
  137. if(StrUtil.isEmpty(tagMap.getValue())){
  138. continue;
  139. }
  140. hasCutModel = true;
  141. break;
  142. }
  143. //更改热点状态
  144. sceneEditInfoExtService.update(
  145. new LambdaUpdateWrapper<SceneEditInfoExt>()
  146. .set(SceneEditInfoExt::getCutModel, hasCutModel ? CommonStatus.YES.code().intValue() : CommonStatus.NO.code().intValue())
  147. .eq(SceneEditInfoExt::getScenePlusId,scenePlusId));
  148. }
  149. private void addOrUpdate(String num, List<JSONObject> data) throws Exception{
  150. Map<String, String> addOrUpdateMap = new HashMap<>();
  151. int i = 0;
  152. for (JSONObject jsonObject : data) {
  153. jsonObject.put("createTime", Calendar.getInstance().getTimeInMillis() + i++);
  154. addOrUpdateMap.put(jsonObject.getString("sid"), JSON.toJSONString(jsonObject));
  155. }
  156. this.syncFileToRedis(num);
  157. //处理新增和修改数据
  158. this.addOrUpdateHandler(num, addOrUpdateMap);
  159. }
  160. private void addOrUpdateHandler(String num, Map<String, String> addOrUpdateMap){
  161. if(CollUtil.isEmpty(addOrUpdateMap))
  162. return;
  163. //批量写入缓存
  164. String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
  165. redisUtil.hmset(key, addOrUpdateMap);
  166. //写入本地文件,作为备份
  167. this.writeFile(num);
  168. }
  169. private void writeFile(String num){
  170. String lockKey = String.format(RedisLockKey.LOCK_CUT_MODEL_SYNC, num);
  171. String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
  172. boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
  173. if(!lock){
  174. return;
  175. }
  176. try{
  177. String dataKey = String.format(RedisKey.SCENE_CUT_MODEL, num);
  178. String cutModelJsonPath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + CUT_MODEL_JSON_NAME;
  179. if(!redisUtil.hasKey(dataKey)){
  180. FileUtil.del(cutModelJsonPath);
  181. return;
  182. }
  183. Map<String, String> cutModelmap = redisUtil.hmget(dataKey);
  184. List<JSONObject> list = cutModelmap.entrySet().stream().map(entry->JSON.parseObject(entry.getValue())).collect(Collectors.toList());
  185. FileUtil.writeUtf8String(JSON.toJSONString(list), cutModelJsonPath);
  186. }finally {
  187. redisLockUtil.unlockLua(lockKey, lockVal);
  188. }
  189. }
  190. private void syncFileToRedis(String num) throws Exception{
  191. String key = String.format(RedisKey.SCENE_CUT_MODEL, num);
  192. boolean exist = redisUtil.hasKey(key);
  193. if(exist){
  194. return;
  195. }
  196. String lockKey = String.format(RedisLockKey.LOCK_CUT_MODEL_SYNC, num);
  197. String lockVal = cn.hutool.core.lang.UUID.randomUUID().toString();
  198. boolean lock = redisLockUtil.lock(lockKey, lockVal, RedisKey.EXPIRE_TIME_1_MINUTE);
  199. if(!lock){
  200. throw new BusinessException(ErrorCode.SYSTEM_BUSY);
  201. }
  202. try{
  203. exist = redisUtil.hasKey(key);
  204. if(exist){
  205. return;
  206. }
  207. String cutModelFilePath = String.format(ConstantFilePath.SCENE_USER_PATH_V4, num) + CUT_MODEL_JSON_NAME;
  208. String cutModelData = FileUtils.readUtf8String(cutModelFilePath);
  209. if(StrUtil.isEmpty(cutModelData)){
  210. return;
  211. }
  212. JSONArray tagsArr = JSON.parseArray(cutModelData);
  213. if(CollUtil.isEmpty(tagsArr)){
  214. return;
  215. }
  216. Map<String, String> map = new HashMap<>();
  217. for (Object o : tagsArr) {
  218. JSONObject jo = (JSONObject)o;
  219. map.put(jo.getString("sid"), jo.toJSONString());
  220. }
  221. redisUtil.hmset(key, map);
  222. }finally {
  223. redisLockUtil.unlockLua(lockKey, lockVal);
  224. }
  225. }
  226. }