问题:由于处理业务逻辑中开启了事务,并且在事务中修改数据,随后使用消息队列MQ异步添加到ES中,由于处理文档流程未提交事务(MQ消费过快),在添加到ES过程查询的数据不是最新的,导致同步到ES的数据不完整
旧代码:
/**
* 批量添加文件关联
* @param fileModuleVo
* @return
*/
@Transactional(rollbackFor = Exception.class)
public ResultMsg fileRelevanceModule(List<FileModuleVo> fileModuleVo) {
for (FileModuleVo moduleVo : fileModuleVo) {
// 1、修改已上传的文件
sysUserFileLogService.updateById(new SysUserFileLog(moduleVo.getFileLogId(), moduleVo.getSourceType(), moduleVo.getIsCooperate() + 1, moduleVo.getMatterName(), moduleVo.getFileGroup(), moduleVo.getClassId()));
// 2、添加文件关联
if (!moduleVo.getModalList().isEmpty()){
List<SysFileRelevanceModule> modules = new ArrayList<>();
for (ModalListVo modalListVo : moduleVo.getModalList()) {
SysFileRelevanceModule module = new SysFileRelevanceModule();
BeanUtils.copyProperties(moduleVo, module);
BeanUtils.copyProperties(modalListVo, module);
module.setRelevanceId(StringUtils.isNotBlank(moduleVo.getRelevanceId()) ? moduleVo.getRelevanceId():modalListVo.getAgendaMatterRelatableId());
module.setRelevanceName(StringUtils.isNotBlank(moduleVo.getRelevanceId()) ? moduleVo.getRelevanceName():modalListVo.getAgendaMatterRelatableName());
modules.add(module);
}
super.saveBatch(modules);
}else{
SysFileRelevanceModule module = new SysFileRelevanceModule();
BeanUtils.copyProperties(moduleVo, module);
super.save(module);
}
}
// 同步搜索引擎
rabbitMQSend.fileLogUpload(fileModuleVo);
return ResultMsg.success(fileModuleVo);
}
/**
* 投递文档上传日志
*/
public void fileLogUpload(List<FileModuleVo> fileModuleVo) {
try {
task.rabbitTemplate.convertAndSend(RabbitMqConst.FILE_LOG_DIRECT_EXCHANGE, RabbitMqConst.FILE_LOG_ROUTING_KEY, fileModuleVo);
} catch (Exception e) {
log.error("文档同步搜索引擎投递失败:{}", JSON.toJSONString(fileModuleVo));
}
}
/**
* 同步到ES
*/
@RabbitListener(queues = RabbitMqConst.FILE_LOG_QUEUE)
public void fileLogSyncEs(List<FileModuleVo> fileModuleVo) {
// 1、组装数据
List<EsDocumentVo> params = new CopyOnWriteArrayList<>();
for (FileModuleVo moduleVo : fileModuleVo) {
// TODO 由于处理【批量添加文件关联】事务未提交,查询的数据不是更新后的
SysUserFileLog fileLogInfo = fileLogService.getById(moduleVo.getFileLogId());
// 文档添加上级
sysUserService.userLeaders(fileLogInfo.getEnterpriseId(), fileLogInfo.getUserId(), moduleVo.getFileLogId(), moduleVo.getUserIds());
if (moduleVo.getSourceType() != 1) continue;
EsDocumentVo documentVo = new EsDocumentVo();
documentVo.setId(moduleVo.getFileLogId());
documentVo.setUserId(fileLogInfo.getUserId());
documentVo.setUserName(fileLogInfo.getUserName());
documentVo.setUserAvatar(fileLogInfo.getUserAvatar());
documentVo.setUsers(sysUserFileRelevanceService.getUsers(moduleVo.getFileLogId()));
documentVo.setEnterpriseId(fileLogInfo.getEnterpriseId());
documentVo.setEnterpriseName(fileLogInfo.getEnterpriseName());
documentVo.setFoldUrl(fileLogInfo.getFolderUrl());
documentVo.setOldFileName(fileLogInfo.getOldFileName());
documentVo.setFileName(fileLogInfo.getFileName());
documentVo.setCompileFileName(fileLogInfo.getCompileFileName());
documentVo.setFileVisitSite(fileLogInfo.getFileVisitSite());
documentVo.setFileType(fileLogInfo.getFileType());
documentVo.setFileSize(fileLogInfo.getFileSize());
documentVo.setUploadTime(fileLogInfo.getUploadTime().toInstant(ZoneOffset.ofHours(8)).toEpochMilli());
documentVo.setSourceType(fileLogInfo.getSourceType());
documentVo.setDocSource(moduleVo.getIsCooperate() + 1);
documentVo.setDocTitle(moduleVo.getMatterName());
if (null != fileLogInfo.getFileGroup()) {
documentVo.setFileGroup(fileLogInfo.getFileGroup().getName());
documentVo.setStatus(agendaMatterService.isApprove(fileLogInfo.getEnterpriseId(), fileLogInfo.getFileGroup().name()) == 0?1:0);
}else {
documentVo.setStatus(1);
}
documentVo.setClassId(fileLogInfo.getClassId());
documentVo.setClassName(sysFileClassService.getClassName(fileLogInfo.getClassId()));
documentVo.setModuleVos(common.extract(moduleVo));
params.add(documentVo);
}
// 2、同步到搜索引擎
if (params.size() > 0){
esDocumentService.saveEs(params);
}
}
处理方法:在事务方法中,提交事务的时候再发起异步消费
/**
* 批量添加文件关联
* @param fileModuleVo
* @return
*/
@Transactional(rollbackFor = Exception.class)
public ResultMsg fileRelevanceModule(List<FileModuleVo> fileModuleVo) {
for (FileModuleVo moduleVo : fileModuleVo) {
// 1、修改已上传的文件
sysUserFileLogService.updateById(new SysUserFileLog(moduleVo.getFileLogId(), moduleVo.getSourceType(), moduleVo.getIsCooperate() + 1, moduleVo.getMatterName(), moduleVo.getFileGroup(), moduleVo.getClassId()));
// 2、添加文件关联
if (!moduleVo.getModalList().isEmpty()){
List<SysFileRelevanceModule> modules = new ArrayList<>();
for (ModalListVo modalListVo : moduleVo.getModalList()) {
SysFileRelevanceModule module = new SysFileRelevanceModule();
BeanUtils.copyProperties(moduleVo, module);
BeanUtils.copyProperties(modalListVo, module);
module.setRelevanceId(StringUtils.isNotBlank(moduleVo.getRelevanceId()) ? moduleVo.getRelevanceId():modalListVo.getAgendaMatterRelatableId());
module.setRelevanceName(StringUtils.isNotBlank(moduleVo.getRelevanceId()) ? moduleVo.getRelevanceName():modalListVo.getAgendaMatterRelatableName());
modules.add(module);
}
super.saveBatch(modules);
}else{
SysFileRelevanceModule module = new SysFileRelevanceModule();
BeanUtils.copyProperties(moduleVo, module);
super.save(module);
}
}
// 同步搜索引擎
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
// 发送消息给MQ
rabbitMQSend.fileLogUpload(fileModuleVo);
}
});
return ResultMsg.success(fileModuleVo);
}
提交事务的时候再使用MQ发起异步消费