提交 2547b6b1 作者: 洪东保

分布式锁

父级 5833b2e8
package com.cmeeting.constant;
/**
* 会议处理状态枚举类
*/
public enum MeetingState {
/**
* 会议状态枚举类型
*/
// 新会议待处理
NEW(0, "新会议待处理"),
// 处理中
GENERATE_ERROR(1, "处理中"),
// 生成纪要成功
NOTE_GENERATED(2, "生成纪要成功"),
// 推送纪要成功
PUSH_SUCCESS(3, "推送纪要邮件成功"),
PUSH_ERROR(4, "推送纪要邮件失败");
// 状态码
private final int code;
// 状态描述
private final String description;
/**
* 枚举构造方法
* @param code 状态码
* @param description 状态描述
*/
private MeetingState(int code, String description) {
this.code = code;
this.description = description;
}
// 获取状态码
public int getCode() {
return code;
}
// 获取状态描述
public String getDescription() {
return description;
}
/**
* 根据状态码获取状态枚举值
* @param code 状态码
* @return 对应的枚举值,若不存在则返回null
*/
public static MeetingState fromCode(int code) {
for (MeetingState state : values()) {
if (state.code == code) {
return state;
}
}
return null;
}
/**
* 扩展方法示例:获取状态类型描述
* @return 返回状态类型描述
*/
public String getTypeDescription() {
return "会议处理状态";
}
}
\ No newline at end of file
package com.cmeeting.job;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cmeeting.constant.MeetingState;
import com.cmeeting.dto.UserDTO;
import com.cmeeting.mapper.primary.UserIdMapper;
import com.cmeeting.pojo.MeetingInfo;
......@@ -146,6 +147,7 @@ public class CmeetingJob {
List<MeetingInfo> meetingInfoList =
meetingInfoService.list(new LambdaQueryWrapper<MeetingInfo>()
.eq(MeetingInfo::getIsGenerated,Boolean.FALSE)
.eq(MeetingInfo::getStatus, MeetingState.GENERATE_ERROR.getCode())
.eq(MeetingInfo::getGenerateRetry,Boolean.FALSE)
.le(MeetingInfo::getSyncTime,LocalDateTime.now().minusHours(1))
);
......
......@@ -19,6 +19,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cmeeting.ad.util.SecurityUtil;
import com.cmeeting.constant.KnowledgePlatformRouteConstant;
import com.cmeeting.constant.MeetingState;
import com.cmeeting.constant.RecordTemplateConstant;
import com.cmeeting.constant.UserAdminRouteConstant;
import com.cmeeting.dto.DocResultDto;
......@@ -96,6 +97,7 @@ public class FileProcessTask {
private MeetingInfoMapper meetingInfoMapper;
private MinioUtils minioUtils;
private RedisUtils redisUtils;
private EmailSender emailSender;
private MeetingRecordTemplateMapper meetingRecordTemplateMapper;
private ProcessLogService processLogService;
......@@ -110,9 +112,15 @@ public class FileProcessTask {
private String fileDownloadPath;
private String permTenantId;
// 实际处理逻辑
public void process() {
boolean isSuccess = false;
String key = "meet_process" + meetingId + "_" + (subMeetingId != null ? "" : "subMeetingId");
if (!redisUtils.setnx(key, 1, 20 * 60)) {
log.warn("key already exists in redis!, key: {}", key);
return;
}
while (retryCount <= MAX_RETRY && !isSuccess) {
Client client = new Client.Builder()
.withAppId(tencentAppId).withSdkId(tencentSdkId)
......@@ -361,6 +369,10 @@ public class FileProcessTask {
throw new RuntimeException("重试失败", ie);
}
}
} finally {
if (isSuccess) {
redisUtils.del(key);
}
}
}
......@@ -479,13 +491,14 @@ public class FileProcessTask {
String meetingName;
//转录文件临时存储路径
// String recordContentPath = meetingId + "-recordContent-" + IdUtil.fastSimpleUUID() + ".txt";
String recordContentPath;
String recordContentPath = null;
//生成的xml临时存储路径
String recordXmlPath = meetingId + "-recordXmlPath-" + IdUtil.fastSimpleUUID() + ".xml";
//填充后的会议纪要名称
String meetingMinutesFileName;
//填充后的会议纪要word文件临时路径
String meetingMinutesPath;
boolean success = false;
try {
String subject = meetingInfo.getSubject();
String fileName = String.format(subject + "_转写原文_%s.txt", DateUtil.today());
......@@ -556,27 +569,30 @@ public class FileProcessTask {
meetingMinutesPath = savePath + meetingMinutesFileName + ".docx";
template.writeAndClose(new FileOutputStream(meetingMinutesPath));
processLogService.log(meetingId,subMeetingId,"填充会议纪要成功");
success = true;
} catch (Exception e) {
success = false;
log.error("填充会议纪要失败: {}", e.getMessage(), e);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
processLogService.log(meetingId,subMeetingId,"填充会议纪要失败"+sw.toString());
throw new RuntimeException("填充会议纪要失败");
} finally {
meetingInfoMapper.update(meetingInfo,
new LambdaUpdateWrapper<MeetingInfo>()
.eq(MeetingInfo::getMeetingId,meetingId)
.eq(subMeetingId != null,MeetingInfo::getSubMeetingId,subMeetingId)
.set(MeetingInfo::getRecordContent,recordContentPath)
.set(MeetingInfo::getRecordXml,recordXmlPath)
.set(MeetingInfo::getParticipantUsers,meetingInfo.getParticipantUsers())
.set(MeetingInfo::getIsGenerated,Boolean.TRUE)
.set(MeetingInfo::getTemplateId,meetingRecordTemplate.getId())
.set(MeetingInfo::getTransDocId,meetingInfo.getTransDocId())
.set(MeetingInfo::getSubject,meetingInfo.getSubject())
.set(MeetingInfo::getStatus, success? MeetingState.NOTE_GENERATED.getCode() : MeetingState.GENERATE_ERROR.getCode())
);
}
meetingInfoMapper.update(meetingInfo,
new LambdaUpdateWrapper<MeetingInfo>()
.eq(MeetingInfo::getMeetingId,meetingId)
.eq(subMeetingId != null,MeetingInfo::getSubMeetingId,subMeetingId)
.set(MeetingInfo::getRecordContent,recordContentPath)
.set(MeetingInfo::getRecordXml,recordXmlPath)
.set(MeetingInfo::getParticipantUsers,meetingInfo.getParticipantUsers())
.set(MeetingInfo::getIsGenerated,Boolean.TRUE)
.set(MeetingInfo::getTemplateId,meetingRecordTemplate.getId())
.set(MeetingInfo::getTransDocId,meetingInfo.getTransDocId())
.set(MeetingInfo::getSubject,meetingInfo.getSubject())
);
meetingInfo.setRecordContent(recordContentPath);
meetingInfo.setRecordXml(recordXmlPath);
return savePath + meetingMinutesFileName + ".docx";
......@@ -601,9 +617,10 @@ public class FileProcessTask {
meetingInfoMapper.update(null,
new LambdaUpdateWrapper<MeetingInfo>()
.eq(MeetingInfo::getMeetingId,meetingId)
.eq(MeetingInfo::getMeetingId, meetingId)
.eq(subMeetingId != null,MeetingInfo::getSubMeetingId,subMeetingId)
.set(MeetingInfo::getIsPushed,isPushed)
.set(MeetingInfo::getIsPushed, isPushed)
.set(MeetingInfo::getStatus, isPushed ? MeetingState.PUSH_SUCCESS.getCode() : MeetingState.PUSH_ERROR.getCode())
);
}
......@@ -718,7 +735,7 @@ public class FileProcessTask {
public FileProcessTask(List<String> recordFileIdList, String meetingId, String subMeetingId, String savePath, Map<String, Object> metadata, String tencentAppId,
String tencentSdkId, String tencentSecretId, String tencentSecretKey, String tencentAdminUserId,
MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, EmailSender emailSender, MeetingRecordTemplateMapper meetingRecordTemplateMapper,
MeetingInfoMapper meetingInfoMapper, MinioUtils minioUtils, RedisUtils redisUtils, EmailSender emailSender, MeetingRecordTemplateMapper meetingRecordTemplateMapper,
String llmApiAddr, Boolean finalRetry, ProcessLogService processLogService,List<UserDTO.TemplateAuthorizedUserDTO> authorizedUsers,Map<String,String> tidWidRelations,
UserAdminConfig userAdminConfig, String adminToken, String applicationId,String fileDownloadPath, String permTenantId) {
this.recordFileIdList = recordFileIdList;
......@@ -733,6 +750,7 @@ public class FileProcessTask {
this.subMeetingId = subMeetingId;
this.meetingInfoMapper = meetingInfoMapper;
this.minioUtils = minioUtils;
this.redisUtils = redisUtils;
this.emailSender = emailSender;
this.meetingRecordTemplateMapper = meetingRecordTemplateMapper;
this.llmApiAddr = llmApiAddr;
......
......@@ -91,6 +91,10 @@ public class MeetingInfo implements Serializable {
*/
private Boolean isPushed;
/**
* 会议状态: 0新会议待处理 1生成纪要失败 2生成纪要成功 3推送邮件成功 4推送邮件失败
*/
private Integer status;
/**
* 会议纪要重新生成标识
*/
private Boolean generateRetry;
......
......@@ -9,6 +9,7 @@ import com.cmeeting.mapper.primary.MeetingInfoMapper;
import com.cmeeting.mapper.primary.MeetingRecordTemplateMapper;
import com.cmeeting.pojo.UserId;
import com.cmeeting.util.MinioUtils;
import com.cmeeting.util.RedisUtils;
import com.cmeeting.util.UserAdminConfig;
import com.cmeeting.util.UserAdminTokenUtil;
import com.cmeeting.vo.TencentMeetingVO;
......@@ -60,6 +61,8 @@ public class FileProcessProducer {
@Resource
private MinioUtils minioUtils;
@Resource
private RedisUtils redisUtils;
@Resource
private EmailSender emailSender;
@Resource
private ProcessLogService processLogService;
......@@ -95,6 +98,7 @@ public class FileProcessProducer {
tencentAdminUserId,
meetingInfoMapper,
minioUtils,
redisUtils,
emailSender,
meetingRecordTemplateMapper,
llmApiAddr,
......
package com.cmeeting.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.constant.MeetingState;
import com.cmeeting.dto.UserDTO;
import com.cmeeting.log.service.ProcessLogService;
import com.cmeeting.mapper.primary.AuthMapper;
......@@ -291,6 +292,7 @@ public class TencentMeetingServiceImpl extends ServiceImpl<TecentMeetingMapper,T
.subMeetingId(subMeetingId).generateRetry(Boolean.FALSE).pushRetry(Boolean.FALSE)
.host(hostName)
.hostUid(hostId)
.status(MeetingState.NEW.getCode())
// .participantUsers(participants.stream()
// .map(item->new String(Base64.getDecoder().decode(item.getUserName()))).distinct().collect(Collectors.joining("、")))
.recordFileId(recordFileIdList.stream().collect(Collectors.joining(",")))
......
......@@ -140,6 +140,14 @@ public class RedisUtils {
return false;
}
}
public boolean setnx(String key, Object value, long time) {
try {
return redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论