Browse Source

队列新增权重

master
luogw 4 weeks ago
parent
commit
5c801f7dfd
  1. 20
      src/main/java/com/project/exam/domain/service/impl/AssemblePaperDomainServiceImpl.java
  2. 2
      src/main/java/com/project/interaction/application/impl/AlgorithmApplicationServiceImpl.java
  3. 4
      src/main/java/com/project/interaction/domain/dto/GenerateQuestionQueueDTO.java
  4. 2
      src/main/java/com/project/interaction/domain/service/PostToGenerateQuestionDomainService.java
  5. 4
      src/main/java/com/project/interaction/domain/service/impl/GenerateQuestionQueueServiceImpl.java
  6. 9
      src/main/java/com/project/interaction/domain/service/impl/PostToGenerateQuestionDomainServiceImpl.java
  7. 2
      src/main/java/com/project/interaction/domain/service/impl/SaveClusterDomainServiceImpl.java
  8. 2
      src/main/java/com/project/question/config/QuestionReplenishProperties.java
  9. 2
      src/main/java/com/project/question/domain/service/GenerateQuestionDomainService.java
  10. 10
      src/main/java/com/project/question/domain/service/impl/GenerateQuestionDomainServiceImpl.java
  11. 4
      src/main/java/com/project/question/domain/service/impl/QuestionInventoryDomainServiceImpl.java
  12. 22
      src/main/java/com/project/question/mapper/TaskKnowledgePointMapper.java

20
src/main/java/com/project/exam/domain/service/impl/AssemblePaperDomainServiceImpl.java

@ -19,6 +19,7 @@ import com.project.question.domain.service.TaskKnowledgePointBaseService;
import com.project.question.mapper.QuestionKpRelMapper; import com.project.question.mapper.QuestionKpRelMapper;
import com.project.question.mapper.QuestionMapper; import com.project.question.mapper.QuestionMapper;
import com.project.exam.domain.dto.ExamRecordDTO; import com.project.exam.domain.dto.ExamRecordDTO;
import com.project.question.mapper.TaskKnowledgePointMapper;
import com.project.task.domain.dto.TaskDTO; import com.project.task.domain.dto.TaskDTO;
import com.project.task.domain.dto.TaskUserDTO; import com.project.task.domain.dto.TaskUserDTO;
import com.project.exam.domain.entity.ExamRecordEntity; import com.project.exam.domain.entity.ExamRecordEntity;
@ -55,6 +56,9 @@ public class AssemblePaperDomainServiceImpl implements AssemblePaperDomainServic
@Autowired @Autowired
private TaskKnowledgePointBaseService taskKnowledgePointBaseService; private TaskKnowledgePointBaseService taskKnowledgePointBaseService;
@Autowired
private TaskKnowledgePointMapper taskKnowledgePointMapper;
@Autowired @Autowired
private TaskBaseService taskBaseService; private TaskBaseService taskBaseService;
@ -115,10 +119,12 @@ public class AssemblePaperDomainServiceImpl implements AssemblePaperDomainServic
Set<Long> coveredKpPool = new HashSet<>(); Set<Long> coveredKpPool = new HashSet<>();
// 最终选定题目 // 最终选定题目
List<QuestionDTO> selectedQuestionList = new ArrayList<>(); List<QuestionDTO> selectedQuestionList = new ArrayList<>();
// 分配种子:前N3个多选,中间N1个单选,最后N2个判断 // 分配种子:前N3个多选
List<TaskKnowledgePointDTO> mcSeeds = seedKpList.subList(0, taskDTO.getMultipleChoiceNum()); List<TaskKnowledgePointDTO> mcSeeds = seedKpList.subList(0, taskDTO.getMultipleChoiceNum());
List<TaskKnowledgePointDTO> scSeeds = seedKpList.subList(taskDTO.getMultipleChoiceNum() , taskDTO.getMultipleChoiceNum() + taskDTO.getSingleChoiceNum()); //重新根据库存选取单选、判断
List<TaskKnowledgePointDTO> tfSeeds = seedKpList.subList(taskDTO.getMultipleChoiceNum() + taskDTO.getSingleChoiceNum() , totalQuestionNum); List<TaskKnowledgePointDTO> seedKpListBySupply = selectBySupply(taskDTO);
List<TaskKnowledgePointDTO> scSeeds = seedKpListBySupply.subList(0,taskDTO.getSingleChoiceNum());
List<TaskKnowledgePointDTO> tfSeeds = seedKpListBySupply.subList(taskDTO.getSingleChoiceNum() , taskDTO.getSingleChoiceNum() + taskDTO.getTrueFalseNum());
// 选择单选题 // 选择单选题
pickWithLock(scSeeds, QuestionTypeEnum.SINGLE_CHOICE , selectedQuestionList, coveredKpPool); pickWithLock(scSeeds, QuestionTypeEnum.SINGLE_CHOICE , selectedQuestionList, coveredKpPool);
// 选择判断题 // 选择判断题
@ -219,6 +225,14 @@ public class AssemblePaperDomainServiceImpl implements AssemblePaperDomainServic
.toList(); .toList();
} }
/**
* 根据单选题库存选取
*/
private List<TaskKnowledgePointDTO> selectBySupply(TaskDTO dto){
return taskKnowledgePointMapper.selectKpOrderBySingle(dto.getId());
}
/** /**
* 通用的普通题抽取逻辑 KP 级别 * 通用的普通题抽取逻辑 KP 级别
*/ */

2
src/main/java/com/project/interaction/application/impl/AlgorithmApplicationServiceImpl.java

@ -41,7 +41,7 @@ public class AlgorithmApplicationServiceImpl implements AlgorithmApplicationServ
@Override @Override
public void postToGenerateQuestion(List<TaskKnowledgePointDTO> dtoList, QuestionTypeEnum questionType, int num) throws Exception { public void postToGenerateQuestion(List<TaskKnowledgePointDTO> dtoList, QuestionTypeEnum questionType, int num) throws Exception {
postToGenerateQuestionDomainService.postToGenerateQuestion(dtoList , questionType , num); postToGenerateQuestionDomainService.postToGenerateQuestion(dtoList , questionType , num, false);
} }

4
src/main/java/com/project/interaction/domain/dto/GenerateQuestionQueueDTO.java

@ -44,5 +44,9 @@ public class GenerateQuestionQueueDTO implements Serializable {
/** 最后一次重试的时间 */ /** 最后一次重试的时间 */
private LocalDateTime lastRetryTime; private LocalDateTime lastRetryTime;
/**权重*/
private Integer weight;
} }

2
src/main/java/com/project/interaction/domain/service/PostToGenerateQuestionDomainService.java

@ -10,7 +10,7 @@ public interface PostToGenerateQuestionDomainService {
/** /**
* 生成题目 * 生成题目
*/ */
void postToGenerateQuestion(List<TaskKnowledgePointDTO> dtoList, QuestionTypeEnum questionType, int num) throws Exception; void postToGenerateQuestion(List<TaskKnowledgePointDTO> dtoList, QuestionTypeEnum questionType, int num, Boolean flage) throws Exception;
/** /**
* 处理队列中的待重试项 * 处理队列中的待重试项

4
src/main/java/com/project/interaction/domain/service/impl/GenerateQuestionQueueServiceImpl.java

@ -26,11 +26,13 @@ public class GenerateQuestionQueueServiceImpl implements GenerateQuestionQueueSe
private PriorityBlockingQueue<GenerateQuestionQueueDTO> queue; private PriorityBlockingQueue<GenerateQuestionQueueDTO> queue;
/*按照权限降序、时间升序*/
@PostConstruct @PostConstruct
public void init() { public void init() {
this.queue = new PriorityBlockingQueue<>( this.queue = new PriorityBlockingQueue<>(
10000, 10000,
Comparator.comparing(GenerateQuestionQueueDTO::getAddTime) Comparator.comparing(GenerateQuestionQueueDTO::getWeight, Comparator.reverseOrder())
.thenComparing(GenerateQuestionQueueDTO::getAddTime)
.thenComparing(GenerateQuestionQueueDTO::getItemId) .thenComparing(GenerateQuestionQueueDTO::getItemId)
); );
} }

9
src/main/java/com/project/interaction/domain/service/impl/PostToGenerateQuestionDomainServiceImpl.java

@ -80,7 +80,7 @@ public class PostToGenerateQuestionDomainServiceImpl implements PostToGenerateQu
* 3. 如果算法服务失败使用熔断降级方案生成默认题目 * 3. 如果算法服务失败使用熔断降级方案生成默认题目
*/ */
@Override @Override
public void postToGenerateQuestion(List<TaskKnowledgePointDTO> dtoList, QuestionTypeEnum questionType, int num) throws Exception { public void postToGenerateQuestion(List<TaskKnowledgePointDTO> dtoList, QuestionTypeEnum questionType, int num, Boolean flage) throws Exception {
Long taskId = Optional.of(dtoList.stream().findFirst()) Long taskId = Optional.of(dtoList.stream().findFirst())
.get().orElse(new TaskKnowledgePointDTO()).getTaskId(); .get().orElse(new TaskKnowledgePointDTO()).getTaskId();
Long clusterId = Optional.of(dtoList.stream().findFirst()) Long clusterId = Optional.of(dtoList.stream().findFirst())
@ -127,6 +127,7 @@ public class PostToGenerateQuestionDomainServiceImpl implements PostToGenerateQu
generateQuestionQueueItem.setNum(num); generateQuestionQueueItem.setNum(num);
generateQuestionQueueItem.setDtoList(dtoList); generateQuestionQueueItem.setDtoList(dtoList);
generateQuestionQueueItem.setTaskId(dtoList.get(0).getTaskId()); generateQuestionQueueItem.setTaskId(dtoList.get(0).getTaskId());
generateQuestionQueueItem.setWeight(flage ? 1 : 0);
generateQuestionQueueService.addItem(generateQuestionQueueItem); generateQuestionQueueService.addItem(generateQuestionQueueItem);
return; return;
} }
@ -137,7 +138,7 @@ public class PostToGenerateQuestionDomainServiceImpl implements PostToGenerateQu
taskId); taskId);
//消息提醒 //消息提醒
// notifyUtil.notify(taskId, clusterId); notifyUtil.notify(taskId, clusterId);
} }
/** /**
@ -275,8 +276,8 @@ public class PostToGenerateQuestionDomainServiceImpl implements PostToGenerateQu
int statusCode = exception.getStatusCode().value(); int statusCode = exception.getStatusCode().value();
if (statusCode == REJECT_STATUS) { if (statusCode == REJECT_STATUS) {
log.warn(">>> [队列管理] 重试仍被拒绝, ItemId: {}", log.warn(">>> [队列管理] 重试仍被拒绝, ItemId: {},TaskId: {}",
item.getItemId(), exception.getMessage()); item.getItemId(), item.getTaskId());
item.setLastRetryTime(LocalDateTime.now()); item.setLastRetryTime(LocalDateTime.now());
item.setRetryCount(item.getRetryCount() + 1); item.setRetryCount(item.getRetryCount() + 1);
return true; return true;

2
src/main/java/com/project/interaction/domain/service/impl/SaveClusterDomainServiceImpl.java

@ -215,7 +215,7 @@ public class SaveClusterDomainServiceImpl implements SaveClusterDomainService {
int generateNum = Math.min(ROUND_NUM, needCount); int generateNum = Math.min(ROUND_NUM, needCount);
// 调用生成方法 // 调用生成方法
generateQuestionDomainService.produce(dto.getSourceId(), type, dto.getSourceType(), generateNum); generateQuestionDomainService.produce(dto.getSourceId(), type, dto.getSourceType(), generateNum, false);
// 更新剩余数量 // 更新剩余数量
int remainCount = needCount - generateNum; int remainCount = needCount - generateNum;

2
src/main/java/com/project/question/config/QuestionReplenishProperties.java

@ -13,7 +13,7 @@ public class QuestionReplenishProperties {
// 闲时结束 // 闲时结束
private int offPeakEnd = 8; private int offPeakEnd = 8;
// 忙时间隔 // 忙时间隔
private int busyInterval = 30; private int busyInterval = 60;
// 闲时间隔 // 闲时间隔
private int offPeakInterval = 180; private int offPeakInterval = 180;
} }

2
src/main/java/com/project/question/domain/service/GenerateQuestionDomainService.java

@ -5,5 +5,5 @@ import com.project.task.domain.enums.QuestionTypeEnum;
public interface GenerateQuestionDomainService { public interface GenerateQuestionDomainService {
void produce(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int needCount); void produce(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int needCount, Boolean flage);
} }

10
src/main/java/com/project/question/domain/service/impl/GenerateQuestionDomainServiceImpl.java

@ -35,32 +35,32 @@ public class GenerateQuestionDomainServiceImpl implements GenerateQuestionDomain
private PostToGenerateQuestionDomainService postToGenerateQuestionDomainService; private PostToGenerateQuestionDomainService postToGenerateQuestionDomainService;
@Override @Override
public void produce(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int needCount) { public void produce(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int needCount, Boolean flage) {
if (needCount <= 0) { if (needCount <= 0) {
return; return;
} }
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
log.info(">>> [题库预生成] 准备生产任务: SourceID={}, Type={}, Count={}", sourceId, sourceType, needCount); log.info(">>> [题库预生成] 准备生产任务: SourceID={}, Type={}, Count={}", sourceId, sourceType, needCount);
Try.run(() -> processBatch(sourceId,questionType , sourceType , needCount)); Try.run(() -> processBatch(sourceId,questionType , sourceType , needCount, flage));
}, questionGenExecutor); }, questionGenExecutor);
} }
private void processBatch(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int count) throws Exception{ private void processBatch(Long sourceId, QuestionTypeEnum questionType , QuestionSourceTypeEnum sourceType, int count, Boolean flage) throws Exception{
// 如果是簇复合题,执行随机采样 2-4 个知识点 // 如果是簇复合题,执行随机采样 2-4 个知识点
List<TaskKnowledgePointDTO> kpList; List<TaskKnowledgePointDTO> kpList;
if (QuestionSourceTypeEnum.Multi_Concept.equals(sourceType)) { if (QuestionSourceTypeEnum.Multi_Concept.equals(sourceType)) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
kpList = samplingStrategy.sample(sourceId); // 获取随机组合的 KPs kpList = samplingStrategy.sample(sourceId); // 获取随机组合的 KPs
postToGenerateQuestionDomainService.postToGenerateQuestion(kpList , questionType , 1); postToGenerateQuestionDomainService.postToGenerateQuestion(kpList , questionType , 1, flage);
} }
} else { } else {
// 单 KP 逻辑:直接查出对应 KP 的内容 // 单 KP 逻辑:直接查出对应 KP 的内容
kpList = Collections.singletonList(taskKnowledgePointBaseService.getById(sourceId) kpList = Collections.singletonList(taskKnowledgePointBaseService.getById(sourceId)
.toDTO(TaskKnowledgePointDTO::new)); .toDTO(TaskKnowledgePointDTO::new));
postToGenerateQuestionDomainService.postToGenerateQuestion(kpList , questionType , count); postToGenerateQuestionDomainService.postToGenerateQuestion(kpList , questionType , count, flage);
} }
} }
} }

4
src/main/java/com/project/question/domain/service/impl/QuestionInventoryDomainServiceImpl.java

@ -150,7 +150,7 @@ public class QuestionInventoryDomainServiceImpl implements QuestionInventoryDoma
int gap = targetLine - currentStock; int gap = targetLine - currentStock;
log.info(">>> [自动补库] KP: {}, 题型: {}, 当前库存: {}, 需补货: {}", kpId, type.getDescription(), currentStock, gap); log.info(">>> [自动补库] KP: {}, 题型: {}, 当前库存: {}, 需补货: {}", kpId, type.getDescription(), currentStock, gap);
// 触发异步生产逻辑 (内部带 30 分钟冷却锁) // 触发异步生产逻辑 (内部带 30 分钟冷却锁)
generateQuestionDomainService.produce(kpId , type , QuestionSourceTypeEnum.Single_Concept , gap); generateQuestionDomainService.produce(kpId , type , QuestionSourceTypeEnum.Single_Concept , gap,true);
} }
} }
@ -164,7 +164,7 @@ public class QuestionInventoryDomainServiceImpl implements QuestionInventoryDoma
int gap = targetLine - currentStock; int gap = targetLine - currentStock;
log.info(">>> [自动补库] 簇: {}, 类型: 复合多选, 当前库存: {}, 需补货: {}", clusterId, currentStock, gap); log.info(">>> [自动补库] 簇: {}, 类型: 复合多选, 当前库存: {}, 需补货: {}", clusterId, currentStock, gap);
// 簇维度触发,触发异步生产逻辑 // 簇维度触发,触发异步生产逻辑
generateQuestionDomainService.produce(clusterId , QuestionTypeEnum.MULTIPLE_CHOICE , QuestionSourceTypeEnum.Multi_Concept , gap); generateQuestionDomainService.produce(clusterId , QuestionTypeEnum.MULTIPLE_CHOICE , QuestionSourceTypeEnum.Multi_Concept , gap,true);
} }
} }

22
src/main/java/com/project/question/mapper/TaskKnowledgePointMapper.java

@ -1,9 +1,31 @@
package com.project.question.mapper; package com.project.question.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.project.question.domain.dto.TaskKnowledgePointDTO;
import com.project.question.domain.entity.TaskKnowledgePointEntity; import com.project.question.domain.entity.TaskKnowledgePointEntity;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper @Mapper
public interface TaskKnowledgePointMapper extends BaseMapper<TaskKnowledgePointEntity> { public interface TaskKnowledgePointMapper extends BaseMapper<TaskKnowledgePointEntity> {
@Select("SELECT kp.* " +
"FROM evaluator_task_knowledge_point kp " +
"INNER JOIN ( " +
" SELECT " +
" e.kp_id," +
" COUNT(DISTINCT CASE WHEN e.question_type = 1 THEN e.question_id END) AS single," +
" COUNT(DISTINCT CASE WHEN e.question_type = 2 THEN e.question_id END) AS multiple," +
" COUNT(DISTINCT CASE WHEN e.question_type = 3 THEN e.question_id END) AS judgment " +
" FROM evaluator_question_kp_rel e " +
" INNER JOIN evaluator_question q ON e.question_id = q.id " +
" WHERE e.task_id = #{id} " +
" AND q.use_status = 0 " +
" AND q.deleted = 0 AND e.deleted = 0" +
" GROUP BY e.kp_id " +
") AS kp_stats ON kp.id = kp_stats.kp_id " +
"ORDER BY kp_stats.single DESC;")
List<TaskKnowledgePointDTO> selectKpOrderBySingle(@Param("id") Long id);
} }

Loading…
Cancel
Save