You've already forked FrameTour-BE
feat(puzzle): 添加拼图边缘渲染功能
- 集成 PuzzleEdgeWorkerIpInterceptor 拦截器进行 IP 校验 - 添加 PuzzleEdgeWorkerSecurityProperties 配置类 - 创建 PuzzleEdgeRenderTaskController 提供边缘渲染接口 - 添加多种 DTO 类用于边缘渲染任务数据传输 - 创建 PuzzleEdgeRenderTaskEntity 实体和 Mapper 接口 - 实现 PuzzleEdgeRenderTaskService 核心服务逻辑 - 重构 PuzzleGenerateServiceImpl 使用边缘渲染服务 - 移除原有的线程池执行器和同步渲染逻辑 - 添加定时任务处理渲染超时和重试机制 - 实现自动打印队列添加功能
This commit is contained in:
@@ -5,13 +5,13 @@ import cn.hutool.json.JSONUtil;
|
||||
import com.ycwl.basic.model.pc.mp.MpConfigEntity;
|
||||
import com.ycwl.basic.puzzle.dto.PuzzleGenerateRequest;
|
||||
import com.ycwl.basic.puzzle.dto.PuzzleGenerateResponse;
|
||||
import com.ycwl.basic.puzzle.edge.task.PuzzleEdgeRenderTaskService;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleElementEntity;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleGenerationRecordEntity;
|
||||
import com.ycwl.basic.puzzle.entity.PuzzleTemplateEntity;
|
||||
import com.ycwl.basic.puzzle.fill.FillResult;
|
||||
import com.ycwl.basic.puzzle.fill.PuzzleElementFillEngine;
|
||||
import com.ycwl.basic.puzzle.mapper.PuzzleGenerationRecordMapper;
|
||||
import com.ycwl.basic.puzzle.mapper.PuzzleTemplateMapper;
|
||||
import com.ycwl.basic.puzzle.repository.PuzzleRepository;
|
||||
import com.ycwl.basic.puzzle.service.IPuzzleGenerateService;
|
||||
import com.ycwl.basic.puzzle.util.PuzzleDuplicationDetector;
|
||||
@@ -37,9 +37,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 拼图图片生成服务实现
|
||||
@@ -58,17 +55,17 @@ public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService {
|
||||
private final ScenicRepository scenicRepository;
|
||||
private final PuzzleDuplicationDetector duplicationDetector;
|
||||
private final PrinterService printerService;
|
||||
private final ThreadPoolExecutor puzzleGenerateExecutor;
|
||||
private final PuzzleEdgeRenderTaskService puzzleEdgeRenderTaskService;
|
||||
|
||||
public PuzzleGenerateServiceImpl(
|
||||
PuzzleTemplateMapper templateMapper,
|
||||
PuzzleRepository puzzleRepository,
|
||||
PuzzleGenerationRecordMapper recordMapper,
|
||||
@Lazy PuzzleImageRenderer imageRenderer,
|
||||
@Lazy PuzzleElementFillEngine fillEngine,
|
||||
@Lazy ScenicRepository scenicRepository,
|
||||
@Lazy PuzzleDuplicationDetector duplicationDetector,
|
||||
@Lazy PrinterService printerService) {
|
||||
@Lazy PrinterService printerService,
|
||||
PuzzleEdgeRenderTaskService puzzleEdgeRenderTaskService) {
|
||||
this.puzzleRepository = puzzleRepository;
|
||||
this.recordMapper = recordMapper;
|
||||
this.imageRenderer = imageRenderer;
|
||||
@@ -76,14 +73,7 @@ public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService {
|
||||
this.scenicRepository = scenicRepository;
|
||||
this.duplicationDetector = duplicationDetector;
|
||||
this.printerService = printerService;
|
||||
this.puzzleGenerateExecutor = new ThreadPoolExecutor(
|
||||
4,
|
||||
256,
|
||||
30,
|
||||
TimeUnit.SECONDS,
|
||||
new LinkedBlockingQueue<>(256),
|
||||
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||
);;
|
||||
this.puzzleEdgeRenderTaskService = puzzleEdgeRenderTaskService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,6 +89,10 @@ public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService {
|
||||
|
||||
@Override
|
||||
public Long generateAsync(PuzzleGenerateRequest request) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
log.info("开始创建异步拼图边缘渲染任务: templateCode={}, userId={}, faceId={}",
|
||||
request.getTemplateCode(), request.getUserId(), request.getFaceId());
|
||||
|
||||
// 1. 参数校验
|
||||
validateRequest(request);
|
||||
|
||||
@@ -112,27 +106,52 @@ public class PuzzleGenerateServiceImpl implements IPuzzleGenerateService {
|
||||
}
|
||||
Long resolvedScenicId = resolveScenicId(template, request.getScenicId());
|
||||
|
||||
// 3. 创建 PENDING 状态的记录
|
||||
// 3. 查询并排序元素
|
||||
List<PuzzleElementEntity> elements = puzzleRepository.getElementsByTemplateId(template.getId());
|
||||
if (elements.isEmpty()) {
|
||||
throw new IllegalArgumentException("模板没有配置元素: " + request.getTemplateCode());
|
||||
}
|
||||
elements.sort(Comparator.comparing(PuzzleElementEntity::getZIndex,
|
||||
Comparator.nullsFirst(Comparator.naturalOrder())));
|
||||
|
||||
// 4. 构建dynamicData
|
||||
Map<String, String> finalDynamicData = buildDynamicData(template, request, resolvedScenicId, elements);
|
||||
|
||||
// 5. 重复图片检测(可能抛出DuplicateImageException)
|
||||
duplicationDetector.detectDuplicateImages(finalDynamicData, elements);
|
||||
|
||||
// 6. 内容去重检测
|
||||
String contentHash = duplicationDetector.calculateContentHash(finalDynamicData);
|
||||
PuzzleGenerationRecordEntity duplicateRecord = duplicationDetector.findDuplicateRecord(
|
||||
template.getId(), contentHash, resolvedScenicId
|
||||
);
|
||||
if (duplicateRecord != null) {
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
log.info("检测到重复内容,复用历史记录: recordId={}, imageUrl={}, duration={}ms",
|
||||
duplicateRecord.getId(), duplicateRecord.getResultImageUrl(), duration);
|
||||
return duplicateRecord.getId();
|
||||
}
|
||||
|
||||
// 7. 创建生成记录
|
||||
PuzzleGenerationRecordEntity record = createRecord(template, request, resolvedScenicId);
|
||||
record.setStatus(0); // 生成中
|
||||
record.setContentHash(contentHash);
|
||||
recordMapper.insert(record);
|
||||
Long recordId = record.getId();
|
||||
|
||||
log.info("异步拼图生成任务已提交: recordId={}, templateCode={}, 当前队列大小={}",
|
||||
recordId, request.getTemplateCode(), puzzleGenerateExecutor.getQueue().size());
|
||||
// 8. 创建边缘渲染任务
|
||||
Long taskId = puzzleEdgeRenderTaskService.createRenderTask(
|
||||
record,
|
||||
template,
|
||||
elements,
|
||||
finalDynamicData,
|
||||
request.getOutputFormat(),
|
||||
request.getQuality()
|
||||
);
|
||||
|
||||
// 4. 提交到线程池异步执行
|
||||
puzzleGenerateExecutor.execute(() -> {
|
||||
try {
|
||||
doGenerateInternal(request, template, resolvedScenicId, record);
|
||||
} catch (Exception e) {
|
||||
log.error("异步拼图生成失败: recordId={}, templateCode={}",
|
||||
recordId, request.getTemplateCode(), e);
|
||||
recordMapper.updateFail(recordId, e.getMessage());
|
||||
}
|
||||
});
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
log.info("异步拼图任务已进入边缘渲染队列: recordId={}, taskId={}, templateCode={}, duration={}ms",
|
||||
record.getId(), taskId, request.getTemplateCode(), duration);
|
||||
|
||||
return recordId;
|
||||
return record.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user