|
|
@ -79,6 +79,9 @@ public class RegenerateQuestionDomainServiceImpl implements RegenerateQuestionDo |
|
|
@Value("${classicpaper.spare.replenish-delay-ms:10000}") |
|
|
@Value("${classicpaper.spare.replenish-delay-ms:10000}") |
|
|
private long replenishDelayMs; |
|
|
private long replenishDelayMs; |
|
|
|
|
|
|
|
|
|
|
|
@Value("${classicpaper.regenerate.timeout-minutes:20}") |
|
|
|
|
|
private int regenerateTimeoutMinutes; |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
public Result<ClassicPaperQuestionDTO> regenerate(Long paperId, Long paperQuestionId) throws Exception { |
|
|
public Result<ClassicPaperQuestionDTO> regenerate(Long paperId, Long paperQuestionId) throws Exception { |
|
|
@ -206,13 +209,52 @@ public class RegenerateQuestionDomainServiceImpl implements RegenerateQuestionDo |
|
|
.eq(RegenerateQuestionTaskEntity::getPaperQuestionId, paperQuestionId) |
|
|
.eq(RegenerateQuestionTaskEntity::getPaperQuestionId, paperQuestionId) |
|
|
.eq(RegenerateQuestionTaskEntity::getStatus, 0)); |
|
|
.eq(RegenerateQuestionTaskEntity::getStatus, 0)); |
|
|
if (existingTask != null) { |
|
|
if (existingTask != null) { |
|
|
// 已有任务正在生题中,先把 questionId 置空,避免前端看到旧题
|
|
|
// 先把 questionId 置空,避免前端看到旧题(MyBatis-Plus updateById 忽略 null,需用 lambdaUpdate)
|
|
|
paperQuestion.setQuestionId(null); |
|
|
classicPaperQuestionBaseService.lambdaUpdate() |
|
|
classicPaperQuestionBaseService.updateById(paperQuestion); |
|
|
.set(ClassicPaperQuestionEntity::getQuestionId, null) |
|
|
throw new BusinessErrorException("该题目正在重新生题中,请稍后再试"); |
|
|
.eq(ClassicPaperQuestionEntity::getId, paperQuestionId) |
|
|
|
|
|
.update(); |
|
|
|
|
|
|
|
|
|
|
|
// 检查是否超时,超时则重新发
|
|
|
|
|
|
long elapsed = System.currentTimeMillis() - existingTask.getCreateTime().getTime(); |
|
|
|
|
|
if (elapsed > regenerateTimeoutMinutes * 60 * 1000L) { |
|
|
|
|
|
log.info(">>> [经典套题-重新生题-异步] 旧任务超时,重新发起, paperQuestionId={}, 已耗时={}ms", |
|
|
|
|
|
paperQuestionId, elapsed); |
|
|
|
|
|
// 标记旧任务为失败
|
|
|
|
|
|
existingTask.setStatus(2); |
|
|
|
|
|
existingTask.setErrorMessage("超时重发"); |
|
|
|
|
|
regenerateQuestionTaskBaseService.updateById(existingTask); |
|
|
|
|
|
// 不返回,继续往下走创建新任务
|
|
|
|
|
|
} else { |
|
|
|
|
|
throw new BusinessErrorException("该题目正在重新生题中,请稍后再试"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 3. 在置空前先查好原题数据
|
|
|
|
|
|
Long originalQuestionId = paperQuestion.getQuestionId(); |
|
|
|
|
|
if (originalQuestionId == null) { |
|
|
|
|
|
throw new BusinessErrorException("原题目不存在"); |
|
|
|
|
|
} |
|
|
|
|
|
QuestionEntity originalQuestion = questionBaseService.getById(originalQuestionId); |
|
|
|
|
|
if (originalQuestion == null) { |
|
|
|
|
|
throw new BusinessErrorException("原题目不存在"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
List<QuestionKpRelEntity> kpRels = questionKpRelBaseService.list( |
|
|
|
|
|
new LambdaQueryWrapper<QuestionKpRelEntity>() |
|
|
|
|
|
.eq(QuestionKpRelEntity::getQuestionId, originalQuestionId)); |
|
|
|
|
|
if (kpRels.isEmpty()) { |
|
|
|
|
|
throw new BusinessErrorException("原题目没有关联知识点,无法重新生题"); |
|
|
} |
|
|
} |
|
|
|
|
|
List<Long> kpIds = kpRels.stream() |
|
|
|
|
|
.map(QuestionKpRelEntity::getKpId).collect(Collectors.toList()); |
|
|
|
|
|
List<KnowledgePointEntity> knowledgePoints = knowledgePointBaseService.listByIds(kpIds); |
|
|
|
|
|
if (knowledgePoints.isEmpty()) { |
|
|
|
|
|
throw new BusinessErrorException("关联知识点数据不存在"); |
|
|
|
|
|
} |
|
|
|
|
|
QuestionTypeEnum questionType = QuestionTypeEnum.findByValue(originalQuestion.getQuestionType()); |
|
|
|
|
|
|
|
|
// 3. 创建任务记录
|
|
|
// 4. 创建任务记录
|
|
|
String taskId = UUID.randomUUID().toString().replace("-", ""); |
|
|
String taskId = UUID.randomUUID().toString().replace("-", ""); |
|
|
RegenerateQuestionTaskEntity taskEntity = new RegenerateQuestionTaskEntity(); |
|
|
RegenerateQuestionTaskEntity taskEntity = new RegenerateQuestionTaskEntity(); |
|
|
taskEntity.setTaskId(taskId); |
|
|
taskEntity.setTaskId(taskId); |
|
|
@ -221,39 +263,25 @@ public class RegenerateQuestionDomainServiceImpl implements RegenerateQuestionDo |
|
|
taskEntity.setStatus(0); // 进行中
|
|
|
taskEntity.setStatus(0); // 进行中
|
|
|
regenerateQuestionTaskBaseService.save(taskEntity); |
|
|
regenerateQuestionTaskBaseService.save(taskEntity); |
|
|
|
|
|
|
|
|
// 4. 清空 questionId,让回调走提拔分支
|
|
|
// 5. 清空 questionId,让回调走提拔分支(MyBatis-Plus updateById 忽略 null,需用 lambdaUpdate)
|
|
|
paperQuestion.setQuestionId(null); |
|
|
classicPaperQuestionBaseService.lambdaUpdate() |
|
|
classicPaperQuestionBaseService.updateById(paperQuestion); |
|
|
.set(ClassicPaperQuestionEntity::getQuestionId, null) |
|
|
|
|
|
.eq(ClassicPaperQuestionEntity::getId, paperQuestionId) |
|
|
|
|
|
.update(); |
|
|
|
|
|
|
|
|
// 5. 异步执行重新生题逻辑(回调会提拔新题 + 更新 task 状态)
|
|
|
// 6. 异步执行重新生题逻辑(回调会提拔新题 + 更新 task 状态)
|
|
|
CompletableFuture.runAsync(() -> doRegenerateAsync(taskId, paperQuestionId), regenerateExecutor); |
|
|
Long clusterId = knowledgePoints.get(0).getClusterId(); |
|
|
|
|
|
CompletableFuture.runAsync(() -> doRegenerateAsync(taskId, paperQuestionId, knowledgePoints, questionType, clusterId), regenerateExecutor); |
|
|
|
|
|
|
|
|
log.info(">>> [经典套题-重新生题-异步] 任务已提交, taskId={}, paperId={}, paperQuestionId={}", taskId, paperId, paperQuestionId); |
|
|
log.info(">>> [经典套题-重新生题-异步] 任务已提交, taskId={}, paperId={}, paperQuestionId={}", taskId, paperId, paperQuestionId); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private void doRegenerateAsync(String taskId, Long paperQuestionId) { |
|
|
private void doRegenerateAsync(String taskId, Long paperQuestionId, |
|
|
|
|
|
List<KnowledgePointEntity> knowledgePoints, |
|
|
|
|
|
QuestionTypeEnum questionType, Long clusterId) { |
|
|
try { |
|
|
try { |
|
|
// 1. 查询关联记录和原题
|
|
|
|
|
|
ClassicPaperQuestionEntity paperQuestion = classicPaperQuestionBaseService.getById(paperQuestionId); |
|
|
|
|
|
Long questionId = paperQuestion.getQuestionId(); |
|
|
|
|
|
QuestionEntity originalQuestion = questionBaseService.getById(questionId); |
|
|
|
|
|
|
|
|
|
|
|
// 2. 查询知识点
|
|
|
|
|
|
List<QuestionKpRelEntity> kpRels = questionKpRelBaseService.list( |
|
|
|
|
|
new LambdaQueryWrapper<QuestionKpRelEntity>() |
|
|
|
|
|
.eq(QuestionKpRelEntity::getQuestionId, questionId)); |
|
|
|
|
|
List<Long> kpIds = kpRels.stream() |
|
|
|
|
|
.map(QuestionKpRelEntity::getKpId).collect(Collectors.toList()); |
|
|
|
|
|
List<KnowledgePointEntity> knowledgePoints = knowledgePointBaseService.listByIds(kpIds); |
|
|
|
|
|
if (knowledgePoints.isEmpty()) { |
|
|
|
|
|
throw new BusinessErrorException("关联知识点数据不存在"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 异步提交生题任务(回调会提拔新题 + 更新 task 状态)
|
|
|
|
|
|
QuestionTypeEnum questionType = QuestionTypeEnum.findByValue(originalQuestion.getQuestionType()); |
|
|
|
|
|
Long clusterId = knowledgePoints.get(0).getClusterId(); |
|
|
|
|
|
classicPaperQuestionGenerator.generateAsync( |
|
|
classicPaperQuestionGenerator.generateAsync( |
|
|
paperQuestionId, knowledgePoints, questionType, 1, clusterId); |
|
|
paperQuestionId, knowledgePoints, questionType, replenishCount, clusterId); |
|
|
|
|
|
|
|
|
log.info(">>> [经典套题-重新生题-异步] 已提交算法, taskId={}, paperQuestionId={}, 题型={}", |
|
|
log.info(">>> [经典套题-重新生题-异步] 已提交算法, taskId={}, paperQuestionId={}, 题型={}", |
|
|
taskId, paperQuestionId, questionType); |
|
|
taskId, paperQuestionId, questionType); |
|
|
|