package com.infynova.udi.service.helper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.infynova.udi.entity.Task; import com.infynova.udi.entity.TaskRecord; import com.infynova.udi.enums.UdiEnumUtils; import com.infynova.udi.enums.task.TaskMatchStatusEnum; import com.infynova.udi.enums.task.TaskRecordEnum; import com.infynova.udi.enums.task.TaskRecordTypeEnum; import com.infynova.udi.enums.task.TaskStatusEnum; import com.infynova.udi.mapper.TaskMapper; import com.infynova.udi.mapper.TaskRecordMapper; import com.infynova.udi.vo.TaskVo; import org.apache.commons.collections4.CollectionUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.text.SimpleDateFormat; import java.time.Duration; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; /** * @author liudong * 2024/2/29 18:31 * @version 1.0 */ @Component("taskHelper") public class TaskHelper { @Resource private TaskMapper taskMapper; @Resource private TaskRecordMapper taskRecordMapper; @Resource RedisTemplate<String, Object> redisTemplate; /** * 公平锁 */ private final ReentrantLock fairLock = new ReentrantLock(true); public List<TaskVo> getTaskVoList(List<Long> taskIdList){ List<Task> tasks = taskMapper.selectBatchIds(taskIdList); if(CollectionUtils.isEmpty(tasks)){ return Collections.emptyList(); } LambdaQueryWrapper<TaskRecord> queryWrapper = new LambdaQueryWrapper<TaskRecord>(); queryWrapper.in(TaskRecord::getTaskId, taskIdList) .orderByAsc(TaskRecord::getCreateTime); List<TaskRecord> taskRecordList = taskRecordMapper.selectList(queryWrapper); Map<Long, List<TaskRecord>> map = taskRecordList.stream().collect(Collectors.groupingBy(TaskRecord::getTaskId)); List<TaskVo> taskVoList = new ArrayList<>(); for (Task task : tasks) { Long taskId = task.getId(); task.setTaskStatusDesc(UdiEnumUtils.getDescByCode(TaskStatusEnum.class,task.getTaskStatus())); //task.setTaskFileSizeDesc(); task.setTaskMatchStatusDesc(UdiEnumUtils.getDescByCode(TaskMatchStatusEnum.class,task.getTaskMatchStatus())); List<TaskRecord> taskRecords = map.getOrDefault(taskId, Collections.emptyList()); this.setUploadTime(task,taskRecords); this.setMatchTime(task,taskRecords); TaskVo taskVo = TaskVo.builder().task(task).taskRecordList(taskRecords).build(); taskVoList.add(taskVo); } return taskVoList; } public TaskVo getTaskVo(Long taskId){ Task task = taskMapper.selectById(taskId); if(Objects.isNull(task)){ return null; } task.setTaskStatusDesc(UdiEnumUtils.getDescByCode(TaskStatusEnum.class,task.getTaskStatus())); //task.setTaskFileSizeDesc(); task.setTaskMatchStatusDesc(UdiEnumUtils.getDescByCode(TaskMatchStatusEnum.class,task.getTaskMatchStatus())); LambdaQueryWrapper<TaskRecord> queryWrapper = new LambdaQueryWrapper<TaskRecord>(); queryWrapper.eq(TaskRecord::getTaskId, taskId) .orderByAsc(TaskRecord::getCreateTime); List<TaskRecord> taskRecords = taskRecordMapper.selectList(queryWrapper); this.setUploadTime(task,taskRecords); this.setMatchTime(task,taskRecords); return TaskVo.builder().task(task).taskRecordList(taskRecords).build(); } public Map<Long,List<TaskRecord>> getTaskRecordMap(List<Long> taskIdList){ LambdaQueryWrapper<TaskRecord> queryWrapper = new LambdaQueryWrapper<TaskRecord>(); queryWrapper.in(TaskRecord::getTaskId, taskIdList) .orderByAsc(TaskRecord::getCreateTime); List<TaskRecord> taskRecords = taskRecordMapper.selectList(queryWrapper); return taskRecords.stream().collect(Collectors.groupingBy(TaskRecord::getTaskId)); } /** * 获取任务编码 */ public String getTaskNo(){ String taskNo; try { fairLock.lock(); while (true){ taskNo = this.build(); Task task = taskMapper.queryTaskNo(taskNo); if(Objects.isNull(task)){ break; } } return taskNo; }catch (Exception e){ throw e; }finally { // 释放锁 fairLock.unlock(); } } private String build(){ String taskNoPrefix = "T"; SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); Date now = new Date(); String dateStr = sdf.format(now); String redisKey = String.format("UDI:%s:%s", dateStr, taskNoPrefix); int num = redisTemplate.opsForValue().increment(redisKey).intValue(); if (num == 1) { //设置过期时间 redisTemplate.expire(redisKey, 2, TimeUnit.DAYS); } String numStr = num + ""; while (numStr.length() < 4) { numStr = "0" + numStr; } dateStr = taskNoPrefix + dateStr + numStr; return dateStr; } @Transactional(rollbackFor = Exception.class) public Task saveTask(Integer taskFileSize,Integer taskFileCount,String taskFileAddress,Long taskFileId){ // 保存task Task task = new Task(); task.setTaskNo(this.getTaskNo()); task.setTaskStatus(TaskStatusEnum.NEW_TASK.getCode()); task.setTaskFileSize(String.valueOf(taskFileSize)); task.setTaskFileCount(taskFileCount); task.setTaskUploadNum(0); task.setTaskFileAddress(taskFileAddress); task.setTaskFileId(taskFileId); task.setUploadTime(0); task.setTaskMatchStatus(TaskMatchStatusEnum.WAITING.getCode()); task.setMatchTime(0); task.setOperatorId(null);// todo task.setOperator(null);// todo task.setCreateBy(null);// todo task.setCreator(null);// todo task.setCreateTime(LocalDateTime.now()); task.setUpdateTime(LocalDateTime.now()); task.setDelFlag(false); task.setVersion(1); taskMapper.insert(task); // 保存TaskRecord TaskRecord taskRecord = this.getDefaultTaskRecord(task.getId(), TaskRecordEnum.IMPORT_BUILD.getDesc()); taskRecordMapper.insert(taskRecord); return task; } /** * 启动上传状态变更 */ @Transactional(rollbackFor = Exception.class) public void taskStatusUploadStart(Long taskId){ Task task = taskMapper.selectById(taskId); task.setTaskStatus(TaskStatusEnum.UPLOADING.getCode()); task.setUpdateTime(LocalDateTime.now()); taskMapper.updateById(task); TaskRecord taskRecord = this.getUploadTaskRecord(taskId, TaskRecordEnum.UPLOAD_START.getDesc()); taskRecordMapper.insert(taskRecord); } /** * 修改已上传数据 */ public void taskUploadNum(Long taskId,int uploadNum){ Task task = taskMapper.selectById(taskId); int num = task.getTaskUploadNum() + uploadNum; task.setTaskUploadNum(num); task.setUpdateTime(LocalDateTime.now()); taskMapper.updateById(task); } /** * 暂停上传状态变更 */ @Transactional(rollbackFor = Exception.class) public void taskStatusUploadPause(Long taskId){ Task task = taskMapper.selectById(taskId); task.setTaskStatus(TaskStatusEnum.PAUSE.getCode()); task.setUpdateTime(LocalDateTime.now()); taskMapper.updateById(task); TaskRecord taskRecord = this.getUploadTaskRecord(taskId, TaskRecordEnum.UPLOAD_PAUSE.getDesc()); taskRecordMapper.insert(taskRecord); } /** * 上传完成状态变更 */ @Transactional(rollbackFor = Exception.class) public void taskStatusUploadFinish(Long taskId){ Task task = taskMapper.selectById(taskId); task.setTaskStatus(TaskStatusEnum.FINISH.getCode()); task.setUpdateTime(LocalDateTime.now()); taskMapper.updateById(task); TaskRecord taskRecord = this.getUploadTaskRecord(taskId, TaskRecordEnum.UPLOAD_FINISH.getDesc()); taskRecordMapper.insert(taskRecord); } /** * 对码开始 */ @Transactional(rollbackFor = Exception.class) public void taskMatchStatusStart(Long taskId){ Task task = taskMapper.selectById(taskId); if(!Objects.equals(task.getTaskMatchStatus(),TaskMatchStatusEnum.WAITING.getCode())){ return; } task.setTaskMatchStatus(TaskMatchStatusEnum.MATCHING.getCode()); task.setUpdateTime(LocalDateTime.now()); taskMapper.updateById(task); TaskRecord taskRecord = this.getMatchTaskRecord(taskId, TaskRecordEnum.MATCH_START.getDesc()); taskRecordMapper.insert(taskRecord); } /** * 对码完成 */ @Transactional(rollbackFor = Exception.class) public void taskMatchStatusFinish(Long taskId){ Task task = taskMapper.selectById(taskId); task.setTaskMatchStatus(TaskMatchStatusEnum.FINISH.getCode()); task.setUpdateTime(LocalDateTime.now()); taskMapper.updateById(task); TaskRecord taskRecord = this.getMatchTaskRecord(taskId, TaskRecordEnum.MATCH_FINISH.getDesc()); taskRecordMapper.insert(taskRecord); } /** * 删除 */ @Transactional(rollbackFor = Exception.class) public void taskDelete(Long taskId){ Task task = taskMapper.selectById(taskId); task.setTaskStatus(TaskStatusEnum.DELETE.getCode()); task.setUpdateTime(LocalDateTime.now()); task.setDelFlag(true); taskMapper.updateById(task); TaskRecord taskRecord = this.getDefaultTaskRecord(taskId, TaskRecordEnum.DELETE.getDesc()); taskRecordMapper.insert(taskRecord); } public TaskRecord getDefaultTaskRecord(Long taskId,String record){ TaskRecord taskRecord = new TaskRecord(); taskRecord.setTaskId(taskId); taskRecord.setRecord(record); taskRecord.setRecordType(TaskRecordTypeEnum.DEFAULT.getCode()); taskRecord.setCreateBy(null);// todo taskRecord.setCreator(null);// todo taskRecord.setCreateTime(LocalDateTime.now()); return taskRecord; } public TaskRecord getUploadTaskRecord(Long taskId,String record){ TaskRecord taskRecord = new TaskRecord(); taskRecord.setTaskId(taskId); taskRecord.setRecord(record); taskRecord.setRecordType(TaskRecordTypeEnum.UPLOAD.getCode()); taskRecord.setCreateBy(null);// todo taskRecord.setCreator(null);// todo taskRecord.setCreateTime(LocalDateTime.now()); return taskRecord; } public TaskRecord getMatchTaskRecord(Long taskId,String record){ TaskRecord taskRecord = new TaskRecord(); taskRecord.setTaskId(taskId); taskRecord.setRecord(record); taskRecord.setRecordType(TaskRecordTypeEnum.MATCH.getCode()); taskRecord.setCreateBy(null);// todo taskRecord.setCreator(null);// todo taskRecord.setCreateTime(LocalDateTime.now()); return taskRecord; } /** * 设置上传时间 */ public void setUploadTime(Task task,List<TaskRecord> taskRecords){ Integer uploadTime = this.getUploadTime(taskRecords); task.setUploadTime(uploadTime); task.setUploadTimeDesc(this.formatDuration(uploadTime)); } /** * 设置对码时间 */ public void setMatchTime(Task task,List<TaskRecord> taskRecords){ Integer matchTime = this.getMatchTime(taskRecords); task.setMatchTime(matchTime); task.setMatchTimeDesc(this.formatDuration(matchTime)); } /** * 计算对码时间 */ public Integer getMatchTime(List<TaskRecord> recordList){ long matchTimeInSeconds = 0; LocalDateTime startTime = null; for (int i = 0; i < recordList.size(); i++) { TaskRecord currentRecord = recordList.get(i); if (currentRecord.getRecordType() == 2) { // 对码记录 if( Objects.equals(currentRecord.getRecord(),TaskRecordEnum.MATCH_START.getDesc()) ){ startTime = currentRecord.getCreateTime(); } else if (Objects.equals(currentRecord.getRecord(),TaskRecordEnum.MATCH_PAUSE.getDesc())) { // 计算本次对码时间并累加到总对码时间 if (startTime != null) { LocalDateTime pauseTime = currentRecord.getCreateTime(); matchTimeInSeconds += Duration.between(startTime, pauseTime).getSeconds(); startTime = null; } } else if (Objects.equals(currentRecord.getRecord(),TaskRecordEnum.MATCH_FINISH.getDesc())) { // 如果启动但没有暂停,直接计算上传时间 if (startTime != null) { LocalDateTime endTime = currentRecord.getCreateTime(); matchTimeInSeconds += Duration.between(startTime, endTime).getSeconds(); startTime = null; } } } } return Math.toIntExact(matchTimeInSeconds); } /** * 计算上传时间 */ public Integer getUploadTime(List<TaskRecord> recordList){ long matchTimeInSeconds = 0; LocalDateTime startTime = null; for (int i = 0; i < recordList.size(); i++) { TaskRecord currentRecord = recordList.get(i); if (currentRecord.getRecordType() == 1) { // 上传记录 if( Objects.equals(currentRecord.getRecord(),TaskRecordEnum.UPLOAD_START.getDesc()) ){ startTime = currentRecord.getCreateTime(); } else if (Objects.equals(currentRecord.getRecord(),TaskRecordEnum.UPLOAD_PAUSE.getDesc())) { // 计算本次上传时间并累加到总上传时间 if (startTime != null) { LocalDateTime pauseTime = currentRecord.getCreateTime(); matchTimeInSeconds += Duration.between(startTime, pauseTime).getSeconds(); startTime = null; } } else if (Objects.equals(currentRecord.getRecord(),TaskRecordEnum.UPLOAD_FINISH.getDesc())) { // 如果启动但没有暂停,直接计算上传时间 if (startTime != null) { LocalDateTime endTime = currentRecord.getCreateTime(); matchTimeInSeconds += Duration.between(startTime, endTime).getSeconds(); startTime = null; } } } } return Math.toIntExact(matchTimeInSeconds); } /** * 时间转换(秒转特定格式) */ public String formatDuration(int durationInSeconds) { int days = durationInSeconds / (24 * 3600); int hours = (durationInSeconds % (24 * 3600)) / 3600; int minutes = ((durationInSeconds % (24 * 3600)) % 3600) / 60; int seconds = ((durationInSeconds % (24 * 3600)) % 3600) % 60; StringBuilder formattedDuration = new StringBuilder(); if (days > 0) { formattedDuration.append(days).append("天"); } if (hours > 0) { formattedDuration.append(hours).append("小时"); } if (minutes > 0) { formattedDuration.append(minutes).append("分钟"); } if (seconds > 0 || (days == 0 && hours == 0 && minutes == 0)) { formattedDuration.append(seconds).append("秒"); } return formattedDuration.toString().trim(); } }