|
|
@@ -0,0 +1,254 @@
|
|
|
+package com.lingyue.parse.service;
|
|
|
+
|
|
|
+import com.lingyue.parse.entity.ParseTask;
|
|
|
+import com.lingyue.parse.repository.ParseTaskRepository;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.util.Date;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 任务进度更新服务
|
|
|
+ * 供各处理阶段调用,统一更新任务状态
|
|
|
+ *
|
|
|
+ * @author lingyue
|
|
|
+ * @since 2026-01-22
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class TaskProgressService {
|
|
|
+
|
|
|
+ private final ParseTaskRepository parseTaskRepository;
|
|
|
+
|
|
|
+ // 阶段权重(用于计算总进度)
|
|
|
+ private static final int WEIGHT_PARSE = 15;
|
|
|
+ private static final int WEIGHT_RAG = 10;
|
|
|
+ private static final int WEIGHT_STRUCTURED = 15;
|
|
|
+ private static final int WEIGHT_NER = 50;
|
|
|
+ private static final int WEIGHT_GRAPH = 10;
|
|
|
+ private static final int TOTAL_WEIGHT = WEIGHT_PARSE + WEIGHT_RAG + WEIGHT_STRUCTURED + WEIGHT_NER + WEIGHT_GRAPH;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新解析阶段进度
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void updateParseProgress(String documentId, String status, Integer progress) {
|
|
|
+ ParseTask task = parseTaskRepository.findByDocumentId(documentId);
|
|
|
+ if (task == null) {
|
|
|
+ log.warn("任务不存在: documentId={}", documentId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ task.setParseStatus(status);
|
|
|
+ task.setParseProgress(progress);
|
|
|
+ task.setCurrentStep("parse");
|
|
|
+ updateOverallProgress(task);
|
|
|
+
|
|
|
+ parseTaskRepository.updateById(task);
|
|
|
+ log.debug("更新解析进度: documentId={}, status={}, progress={}", documentId, status, progress);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新 RAG 阶段进度
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void updateRagProgress(String documentId, String status, Integer progress) {
|
|
|
+ ParseTask task = parseTaskRepository.findByDocumentId(documentId);
|
|
|
+ if (task == null) {
|
|
|
+ log.warn("任务不存在: documentId={}", documentId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ task.setRagStatus(status);
|
|
|
+ task.setRagProgress(progress);
|
|
|
+ task.setCurrentStep("rag");
|
|
|
+ updateOverallProgress(task);
|
|
|
+
|
|
|
+ parseTaskRepository.updateById(task);
|
|
|
+ log.debug("更新RAG进度: documentId={}, status={}, progress={}", documentId, status, progress);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新结构化解析阶段进度
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void updateStructuredProgress(String documentId, String status, Integer progress,
|
|
|
+ Integer elementCount, Integer imageCount, Integer tableCount) {
|
|
|
+ ParseTask task = parseTaskRepository.findByDocumentId(documentId);
|
|
|
+ if (task == null) {
|
|
|
+ log.warn("任务不存在: documentId={}", documentId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ task.setStructuredStatus(status);
|
|
|
+ task.setStructuredProgress(progress);
|
|
|
+ task.setStructuredElementCount(elementCount);
|
|
|
+ task.setStructuredImageCount(imageCount);
|
|
|
+ task.setStructuredTableCount(tableCount);
|
|
|
+ task.setCurrentStep("structured");
|
|
|
+ updateOverallProgress(task);
|
|
|
+
|
|
|
+ parseTaskRepository.updateById(task);
|
|
|
+ log.debug("更新结构化解析进度: documentId={}, status={}, elements={}", documentId, status, elementCount);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新 NER 阶段进度
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void updateNerProgress(String documentId, String status, Integer progress,
|
|
|
+ String nerTaskId, Integer entityCount, Integer relationCount) {
|
|
|
+ ParseTask task = parseTaskRepository.findByDocumentId(documentId);
|
|
|
+ if (task == null) {
|
|
|
+ log.warn("任务不存在: documentId={}", documentId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ task.setNerStatus(status);
|
|
|
+ task.setNerProgress(progress);
|
|
|
+ if (nerTaskId != null) {
|
|
|
+ task.setNerTaskId(nerTaskId);
|
|
|
+ }
|
|
|
+ if (entityCount != null) {
|
|
|
+ task.setNerEntityCount(entityCount);
|
|
|
+ }
|
|
|
+ if (relationCount != null) {
|
|
|
+ task.setNerRelationCount(relationCount);
|
|
|
+ }
|
|
|
+ task.setCurrentStep("ner");
|
|
|
+ updateOverallProgress(task);
|
|
|
+
|
|
|
+ parseTaskRepository.updateById(task);
|
|
|
+ log.debug("更新NER进度: documentId={}, status={}, progress={}, entities={}",
|
|
|
+ documentId, status, progress, entityCount);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新图构建阶段进度
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void updateGraphProgress(String documentId, String status, Integer progress) {
|
|
|
+ ParseTask task = parseTaskRepository.findByDocumentId(documentId);
|
|
|
+ if (task == null) {
|
|
|
+ log.warn("任务不存在: documentId={}", documentId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ task.setGraphStatus(status);
|
|
|
+ task.setGraphProgress(progress);
|
|
|
+ task.setCurrentStep("graph");
|
|
|
+ updateOverallProgress(task);
|
|
|
+
|
|
|
+ // 如果图构建完成,标记整个任务完成
|
|
|
+ if ("completed".equals(status)) {
|
|
|
+ task.setStatus("completed");
|
|
|
+ task.setProgress(100);
|
|
|
+ task.setCompletedAt(new Date());
|
|
|
+ }
|
|
|
+
|
|
|
+ parseTaskRepository.updateById(task);
|
|
|
+ log.debug("更新图构建进度: documentId={}, status={}, progress={}", documentId, status, progress);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 标记任务失败
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void markFailed(String documentId, String stage, String errorMessage) {
|
|
|
+ ParseTask task = parseTaskRepository.findByDocumentId(documentId);
|
|
|
+ if (task == null) {
|
|
|
+ log.warn("任务不存在: documentId={}", documentId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ task.setStatus("failed");
|
|
|
+ task.setErrorMessage(errorMessage);
|
|
|
+ task.setCurrentStep(stage);
|
|
|
+ task.setCompletedAt(new Date());
|
|
|
+
|
|
|
+ // 标记对应阶段失败
|
|
|
+ switch (stage) {
|
|
|
+ case "parse":
|
|
|
+ task.setParseStatus("failed");
|
|
|
+ break;
|
|
|
+ case "rag":
|
|
|
+ task.setRagStatus("failed");
|
|
|
+ break;
|
|
|
+ case "structured":
|
|
|
+ task.setStructuredStatus("failed");
|
|
|
+ break;
|
|
|
+ case "ner":
|
|
|
+ task.setNerStatus("failed");
|
|
|
+ break;
|
|
|
+ case "graph":
|
|
|
+ task.setGraphStatus("failed");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ parseTaskRepository.updateById(task);
|
|
|
+ log.error("任务失败: documentId={}, stage={}, error={}", documentId, stage, errorMessage);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算并更新总体进度
|
|
|
+ */
|
|
|
+ private void updateOverallProgress(ParseTask task) {
|
|
|
+ int totalProgress = 0;
|
|
|
+
|
|
|
+ // 计算各阶段贡献的进度
|
|
|
+ totalProgress += calculateStageProgress(task.getParseStatus(), task.getParseProgress(), WEIGHT_PARSE);
|
|
|
+ totalProgress += calculateStageProgress(task.getRagStatus(), task.getRagProgress(), WEIGHT_RAG);
|
|
|
+ totalProgress += calculateStageProgress(task.getStructuredStatus(), task.getStructuredProgress(), WEIGHT_STRUCTURED);
|
|
|
+ totalProgress += calculateStageProgress(task.getNerStatus(), task.getNerProgress(), WEIGHT_NER);
|
|
|
+ totalProgress += calculateStageProgress(task.getGraphStatus(), task.getGraphProgress(), WEIGHT_GRAPH);
|
|
|
+
|
|
|
+ // 归一化到 0-100
|
|
|
+ int overallProgress = (totalProgress * 100) / TOTAL_WEIGHT;
|
|
|
+ task.setProgress(Math.min(overallProgress, 100));
|
|
|
+
|
|
|
+ // 更新整体状态
|
|
|
+ if (isAnyFailed(task)) {
|
|
|
+ task.setStatus("failed");
|
|
|
+ } else if (isAllCompleted(task)) {
|
|
|
+ task.setStatus("completed");
|
|
|
+ } else if (isAnyProcessing(task)) {
|
|
|
+ task.setStatus("processing");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private int calculateStageProgress(String status, Integer progress, int weight) {
|
|
|
+ if ("completed".equals(status)) {
|
|
|
+ return weight;
|
|
|
+ } else if ("processing".equals(status) && progress != null) {
|
|
|
+ return (progress * weight) / 100;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isAnyFailed(ParseTask task) {
|
|
|
+ return "failed".equals(task.getParseStatus()) ||
|
|
|
+ "failed".equals(task.getRagStatus()) ||
|
|
|
+ "failed".equals(task.getStructuredStatus()) ||
|
|
|
+ "failed".equals(task.getNerStatus()) ||
|
|
|
+ "failed".equals(task.getGraphStatus());
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isAllCompleted(ParseTask task) {
|
|
|
+ return "completed".equals(task.getParseStatus()) &&
|
|
|
+ "completed".equals(task.getRagStatus()) &&
|
|
|
+ "completed".equals(task.getStructuredStatus()) &&
|
|
|
+ "completed".equals(task.getNerStatus()) &&
|
|
|
+ "completed".equals(task.getGraphStatus());
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isAnyProcessing(ParseTask task) {
|
|
|
+ return "processing".equals(task.getParseStatus()) ||
|
|
|
+ "processing".equals(task.getRagStatus()) ||
|
|
|
+ "processing".equals(task.getStructuredStatus()) ||
|
|
|
+ "processing".equals(task.getNerStatus()) ||
|
|
|
+ "processing".equals(task.getGraphStatus());
|
|
|
+ }
|
|
|
+}
|