media_task_queue.json
¶Ô±ÈÐÂÎļþ @@ -0,0 +1 @@ {"current":null,"queue":[]} yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/manager/MediaTaskManager.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,144 @@ package cn.iocoder.yudao.module.digitalcourse.manager; import cn.iocoder.yudao.module.digitalcourse.model.MediaTask; import cn.iocoder.yudao.module.digitalcourse.service.coursemedia.CourseMediaServiceUtil; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.annotation.Resource; import org.springframework.stereotype.Component; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; /** * @author kanglujie * @date 2025-04-07 14:36:00 */ @Component public class MediaTaskManager { private final BlockingQueue<MediaTask> queue = new LinkedBlockingQueue<>(); private final ExecutorService executor = Executors.newSingleThreadExecutor(); private final ObjectMapper mapper = new ObjectMapper() .registerModule(new JavaTimeModule()) .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); private final Path persistPath = Paths.get("media_task_queue.json"); private final Path persistTempPath = Paths.get("media_task_queue_temp.json"); private final Object lock = new Object(); // é对象 private volatile MediaTask currentTask = null; @Resource private CourseMediaServiceUtil courseMediaServiceUtil; @PostConstruct public void init() throws IOException { mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); loadQueueFromDisk(); startWorker(); } public int submitTask(MediaTask task) throws IOException { synchronized (lock) { queue.add(task); persistQueue(); // ç«å³æä¹ å return queue.size(); } } public int getQueuePosition(Long taskId) { int pos = 1; if (currentTask != null && currentTask.getId().equals(taskId)) return 0; for (MediaTask task : queue) { if (task.getId().equals(taskId)) return pos; pos++; } return -1; } private void startWorker() { executor.submit(() -> { while (true) { try { currentTask = queue.take(); // å¼å§å¤ç persistQueue(); System.out.println("å¼å§åæï¼" + currentTask.getId()); courseMediaServiceUtil.remoteMegerMedia(currentTask.getReq()); synchronized (lock) { currentTask = null; persistQueue(); // æ§è¡å®åæä¹ å } } catch (Exception e) { e.printStackTrace(); // 妿å¼å¸¸äºï¼éæ°å ¥é if (currentTask != null) { queue.add(currentTask); currentTask = null; } persistQueue(); } } }); } private void persistQueue() { synchronized (lock) { try { QueueState state = new QueueState(); state.current = currentTask; state.queue = new ArrayList<>(queue); mapper.writeValue(persistTempPath.toFile(), state); Files.move(persistTempPath, persistPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); } catch (IOException e) { e.printStackTrace(); } } } private void loadQueueFromDisk() { synchronized (lock) { if (Files.exists(persistPath)) { try { QueueState state = mapper.readValue(persistPath.toFile(), QueueState.class); if (state.current != null) { queue.add(state.current); } if (state.queue != null) { queue.addAll(state.queue); } } catch (IOException e) { e.printStackTrace(); } } } } @PreDestroy public void shutdown() { executor.shutdownNow(); persistQueue(); } // å é¨ç±»ç¨äº JSON æ å° public static class QueueState { public MediaTask current; public List<MediaTask> queue; } } yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/model/MediaTask.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,21 @@ package cn.iocoder.yudao.module.digitalcourse.model; /** * @author kanglujie * @date 2025-04-07 14:35:03 */ import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaMegerVO; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.time.LocalDateTime; @Data @NoArgsConstructor @AllArgsConstructor public class MediaTask { private Long id; private CourseMediaMegerVO req; private LocalDateTime submitTime; } yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceImpl.java
@@ -1,38 +1,28 @@ package cn.iocoder.yudao.module.digitalcourse.service.coursemedia; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaMegerVO; import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaPageReqVO; import cn.iocoder.yudao.module.digitalcourse.controller.admin.coursemedia.vo.CourseMediaSaveReqVO; import cn.iocoder.yudao.module.digitalcourse.controller.admin.courses.vo.AppCoursesUpdateReqVO; import cn.iocoder.yudao.module.digitalcourse.dal.dataobject.coursemedia.CourseMediaDO; import cn.iocoder.yudao.module.digitalcourse.dal.mysql.coursemedia.CourseMediaMapper; import cn.iocoder.yudao.module.digitalcourse.manager.MediaTaskManager; import cn.iocoder.yudao.module.digitalcourse.model.MediaTask; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.scheduling.annotation.Async; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import java.math.BigInteger; import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import static cn.iocoder.yudao.module.digitalcourse.enums.ErrorCodeConstants.COURSE_MEDIA_NOT_EXISTS; @@ -115,10 +105,17 @@ } updateReqVO.setCourseMediaId(courseMediaDO.getId()); //弿¥è°ç¨æ°å人è§é¢æ¸²ææ¥å£ï¼å¼å§åå¹¶ courseMediaServiceUtil.remoteMegerMedia(updateReqVO); return CommonResult.success(true); MediaTask task = new MediaTask(id, updateReqVO, LocalDateTime.now()); int pos = 0; try { pos = mediaTaskManager.submitTask(task); } catch (IOException e) { throw new RuntimeException(e); } return CommonResult.success("åæè§é¢æäº¤æåï¼æ¨æå¨ç¬¬ " + (pos+1) + " 个"); } @Resource private MediaTaskManager mediaTaskManager; @Override public CommonResult reMegerMedia(CourseMediaMegerVO updateReqVO) { Long id = updateReqVO.getId(); yudao-module-digitalcourse/yudao-module-digitalcourse-biz/src/main/java/cn/iocoder/yudao/module/digitalcourse/service/coursemedia/CourseMediaServiceUtil.java
@@ -73,9 +73,11 @@ * @param updateReqVO * @return */ @Async public void remoteMegerMedia(CourseMediaMegerVO updateReqVO) { FileUtil.clean("D:/heygem_data/face2face/temp/"); CourseMediaDO courseMediaDO = courseMediaMapper.selectById(updateReqVO.getCourseMediaId()); courseMediaDO.setStatus(1); courseMediaMapper.updateById(courseMediaDO); List<AppCourseScenesMegerReqVO> scenes = updateReqVO.getScenes(); //è·åæ°åäººç´ æï¼å£°é³ãè§é¢ï¼ String entityId = null; @@ -279,7 +281,7 @@ byte[] bytes = FileUtil.readBytes(FileUtil.file("D:/heygem_data/face2face/temp/"+"111111.mp4")); String file = fileApi.createFile(bytes); // 妿æåï¼æ´æ°ç¶æä¸º1ï¼æåï¼ courseMediaDO.setStatus(1); courseMediaDO.setStatus(2); courseMediaDO.setPreviewUrl(file); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date();