后台更新 服务优化
Build Backend JAR / build (push) Failing after 16m54s

This commit is contained in:
supernijia
2026-08-11 14:50:21 +08:00
parent 38216a1885
commit 5b1ccad40e
24 changed files with 1623 additions and 502 deletions
@@ -2678,9 +2678,10 @@ public class AppearancePatentTaskService {
markCozeStateTerminal(state, COZE_STATUS_FAILED, "Coze pending submit task missing");
return;
}
Map<String, AppearancePatentResultRowDto> currentRows = loadPersistedResultRows(task.getId());
Map<String, AppearancePatentResultRowDto> currentRows = loadPersistedResultRowsForResultRows(
task.getId(), batchRows);
List<AppearancePatentResultRowDto> currentBatchRows = batchRows.stream()
.map(row -> currentRows.get(rowKey(row)))
.map(row -> findPersistedResultRow(row, currentRows))
.filter(Objects::nonNull)
.toList();
if (currentBatchRows.size() == batchRows.size()
@@ -3006,45 +3007,48 @@ public class AppearancePatentTaskService {
private void assembleResultWorkbook(FileTaskEntity task, FileResultEntity result) {
AppearancePatentParsedPayloadDto parsed = readParsedPayload(task);
Map<String, AppearancePatentResultRowDto> resultMap = loadPersistedResultRowsWithRetry(task.getId(), parsed.getAllItems().size());
List<AppearancePatentParsedRowVo> receivedRows = filterReceivedParsedRows(parsed.getAllItems(), resultMap);
long resolvedRows = receivedRows.stream()
.filter(row -> findResultRow(row, resultMap) != null)
.count();
long reasonRows = resultMap.values().stream()
.filter(this::hasReasonFields)
.count();
log.info("[appearance-patent] assemble workbook taskId={} parsedRows={} receivedRows={} resultRows={} resolvedRows={} reasonRows={}",
task.getId(), parsed.getAllItems().size(), receivedRows.size(), resultMap.size(), resolvedRows, reasonRows);
if (!parsed.getAllItems().isEmpty() && receivedRows.isEmpty()) {
List<AppearancePatentParsedRowVo> parsedRows = parsed.getAllItems() == null
? List.of() : parsed.getAllItems();
List<SourceRows> sourceRows = splitRowsBySourceFile(parsed, parsedRows, result.getSourceFilename());
if (sourceRows.isEmpty()) {
throw new BusinessException("外观专利检测结果为空,请稍后重试生成结果文件");
}
validateCompleteCozeCoverage(task.getId(), receivedRows, resultMap);
// 公共分组处理:同 baseId 连续行视为一组(如 1、1_1、1_2),组内任一行结论命中
// "已侵权"/"侵权"(包含匹配,"已侵权"优先),则组内所有行结论统一为该标准值。
// 单行组跳过。仅修改 conclusion 列,不影响其他列。
int conclusionPropagated = CozeGroupResultPropagator.propagateByGroup(
receivedRows,
AppearancePatentParsedRowVo::getDisplayId,
row -> findResultRow(row, resultMap),
AppearancePatentResultRowDto::getConclusion,
AppearancePatentResultRowDto::setConclusion,
List.of("已侵权", "侵权"),
"[appearance-patent] taskId=" + task.getId()
);
if (conclusionPropagated > 0) {
log.info("[appearance-patent] group propagate conclusion taskId={} updatedRows={}",
task.getId(), conclusionPropagated);
}
int receivedRowCount = 0;
long resolvedRows = 0L;
long reasonRows = 0L;
int conclusionPropagated = 0;
File outputDir = new File(storageProperties.getLocalTempDir(), "appearance-patent-result");
if (!outputDir.exists() && !outputDir.mkdirs()) {
throw new BusinessException("创建结果目录失败");
}
List<SourceRows> sourceRows = splitRowsBySourceFile(parsed, receivedRows, result.getSourceFilename());
List<SourceResultWorkbook> workbooks = new ArrayList<>();
File zip = null;
try {
for (SourceRows item : sourceRows) {
Map<String, AppearancePatentResultRowDto> resultMap =
loadPersistedResultRowsForRowsWithRetry(task.getId(), item.rows());
List<AppearancePatentParsedRowVo> receivedRows = filterReceivedParsedRows(item.rows(), resultMap);
if (receivedRows.isEmpty()) {
resultMap.clear();
continue;
}
receivedRowCount += receivedRows.size();
resolvedRows += receivedRows.stream()
.filter(row -> findResultRow(row, resultMap) != null)
.count();
reasonRows += resultMap.values().stream()
.filter(this::hasReasonFields)
.count();
validateCompleteCozeCoverage(task.getId(), receivedRows, resultMap);
conclusionPropagated += CozeGroupResultPropagator.propagateByGroup(
receivedRows,
AppearancePatentParsedRowVo::getDisplayId,
row -> findResultRow(row, resultMap),
AppearancePatentResultRowDto::getConclusion,
AppearancePatentResultRowDto::setConclusion,
List.of("已侵权", "侵权"),
"[appearance-patent] taskId=" + task.getId()
);
String filename = safeFileStem(item.sourceFilename()) + "-result.xlsx";
String tempFilename = safeFileStem(item.sourceFilename())
+ "-" + task.getId()
@@ -3052,12 +3056,20 @@ public class AppearancePatentTaskService {
+ "-" + UUID.randomUUID()
+ "-result.xlsx";
File xlsx = new File(outputDir, tempFilename);
writeResultWorkbook(xlsx, parsed, item.rows(), resultMap);
workbooks.add(new SourceResultWorkbook(xlsx, filename, item.rows().size()));
writeResultWorkbook(xlsx, parsed, receivedRows, resultMap);
workbooks.add(new SourceResultWorkbook(xlsx, filename, receivedRows.size()));
resultMap.clear();
}
if (workbooks.isEmpty()) {
throw new BusinessException("外观专利检测结果为空,请稍后重试生成结果文件");
}
log.info("[appearance-patent] assemble workbook taskId={} parsedRows={} receivedRows={} resultRows={} resolvedRows={} reasonRows={}",
task.getId(), parsedRows.size(), receivedRowCount,
workbooks.stream().mapToInt(SourceResultWorkbook::rowCount).sum(), resolvedRows, reasonRows);
if (conclusionPropagated > 0) {
log.info("[appearance-patent] group propagate conclusion taskId={} updatedRows={}",
task.getId(), conclusionPropagated);
}
File uploadFile;
String filename;
@@ -3085,7 +3097,7 @@ public class AppearancePatentTaskService {
result.setResultFileUrl(objectKey);
result.setResultFileSize(uploadFile.length());
result.setResultContentType(contentType);
result.setRowCount(receivedRows.size());
result.setRowCount(receivedRowCount);
} finally {
for (SourceResultWorkbook workbook : workbooks) {
if (workbook.file().exists() && !workbook.file().delete()) {
@@ -3249,18 +3261,6 @@ public class AppearancePatentTaskService {
&& hasUsableCozeField(row.getConclusion());
}
private Map<String, AppearancePatentResultRowDto> loadPersistedResultRows(Long taskId) {
Map<String, AppearancePatentResultRowDto> result = new LinkedHashMap<>();
List<TaskChunkEntity> chunks = taskChunkMapper.selectList(new LambdaQueryWrapper<TaskChunkEntity>()
.eq(TaskChunkEntity::getTaskId, taskId)
.eq(TaskChunkEntity::getModuleType, MODULE_TYPE)
.orderByAsc(TaskChunkEntity::getChunkIndex));
for (TaskChunkEntity chunk : chunks) {
result.putAll(readChunkRows(chunk));
}
return result;
}
private boolean hasPersistedResultRows(Long taskId) {
if (taskId == null) {
return false;
@@ -3271,25 +3271,121 @@ public class AppearancePatentTaskService {
return count != null && count > 0;
}
private Map<String, AppearancePatentResultRowDto> loadPersistedResultRowsWithRetry(Long taskId, int expectedParsedRows) {
Map<String, AppearancePatentResultRowDto> result = loadPersistedResultRows(taskId);
if (expectedParsedRows <= 0 || !result.isEmpty()) {
private Map<String, AppearancePatentResultRowDto> loadPersistedResultRowsForRowsWithRetry(
Long taskId, List<AppearancePatentParsedRowVo> requestedRows) {
Set<String> requestedKeys = resultLookupKeysForParsedRows(requestedRows);
Map<String, AppearancePatentResultRowDto> result =
loadPersistedResultRowsForKeys(taskId, requestedKeys);
if (requestedKeys.isEmpty() || !result.isEmpty()) {
return result;
}
for (int attempt = 1; attempt <= RESULT_ROWS_READ_RETRY_LIMIT && result.isEmpty(); attempt++) {
sleepBeforeResultRowsRetry(attempt);
result = loadPersistedResultRows(taskId);
result = loadPersistedResultRowsForKeys(taskId, requestedKeys);
if (!result.isEmpty()) {
log.info("[appearance-patent] result rows recovered after retry taskId={} attempt={} rows={}",
taskId, attempt, result.size());
return result;
}
log.warn("[appearance-patent] result rows still empty after retry taskId={} attempt={}/{}",
taskId, attempt, RESULT_ROWS_READ_RETRY_LIMIT);
}
return result;
}
private Map<String, AppearancePatentResultRowDto> loadPersistedResultRowsForResultRows(
Long taskId, List<AppearancePatentResultRowDto> requestedRows) {
Set<String> requestedKeys = resultLookupKeysForResultRows(requestedRows);
return loadPersistedResultRowsForKeys(taskId, requestedKeys);
}
private Map<String, AppearancePatentResultRowDto> loadPersistedResultRowsForKeys(
Long taskId, Set<String> requestedKeys) {
Map<String, AppearancePatentResultRowDto> result = new LinkedHashMap<>();
if (taskId == null || requestedKeys == null || requestedKeys.isEmpty()) {
return result;
}
Long lastChunkId = null;
while (true) {
LambdaQueryWrapper<TaskChunkEntity> query = new LambdaQueryWrapper<TaskChunkEntity>()
.eq(TaskChunkEntity::getTaskId, taskId)
.eq(TaskChunkEntity::getModuleType, MODULE_TYPE)
.orderByAsc(TaskChunkEntity::getId)
.last("LIMIT 1");
if (lastChunkId != null) {
query.gt(TaskChunkEntity::getId, lastChunkId);
}
List<TaskChunkEntity> page = taskChunkMapper.selectList(query);
if (page == null || page.isEmpty()) {
break;
}
TaskChunkEntity chunk = page.getFirst();
appendRequestedResultRows(result, readChunkRows(chunk).values(), requestedKeys);
lastChunkId = chunk.getId();
if (lastChunkId == null) {
break;
}
}
return result;
}
private Set<String> resultLookupKeysForParsedRows(List<AppearancePatentParsedRowVo> rows) {
Set<String> keys = new LinkedHashSet<>();
for (AppearancePatentParsedRowVo row : rows == null ? List.<AppearancePatentParsedRowVo>of() : rows) {
String primary = rowKey(row);
if (!primary.isBlank()) {
keys.add(primary);
}
String legacy = legacyRowKey(row);
if (!legacy.isBlank()) {
keys.add(legacy);
}
}
return keys;
}
private Set<String> resultLookupKeysForResultRows(List<AppearancePatentResultRowDto> rows) {
Set<String> keys = new LinkedHashSet<>();
for (AppearancePatentResultRowDto row : rows == null ? List.<AppearancePatentResultRowDto>of() : rows) {
String primary = rowKey(row);
if (!primary.isBlank()) {
keys.add(primary);
}
String legacy = legacyRowKey(row);
if (!legacy.isBlank()) {
keys.add(legacy);
}
}
return keys;
}
private void appendRequestedResultRows(Map<String, AppearancePatentResultRowDto> sink,
Iterable<AppearancePatentResultRowDto> rows,
Set<String> requestedKeys) {
if (rows == null || requestedKeys == null || requestedKeys.isEmpty()) {
return;
}
for (AppearancePatentResultRowDto row : rows) {
if (row == null) {
continue;
}
String primary = rowKey(row);
String legacy = legacyRowKey(row);
String matchedKey = requestedKeys.contains(primary)
? primary : requestedKeys.contains(legacy) ? legacy : "";
if (!matchedKey.isBlank()) {
sink.put(matchedKey, row);
}
}
}
private AppearancePatentResultRowDto findPersistedResultRow(
AppearancePatentResultRowDto row,
Map<String, AppearancePatentResultRowDto> resultMap) {
if (row == null || resultMap == null || resultMap.isEmpty()) {
return null;
}
AppearancePatentResultRowDto result = resultMap.get(rowKey(row));
return result == null ? resultMap.get(legacyRowKey(row)) : result;
}
private void sleepBeforeResultRowsRetry(int attempt) {
try {
Thread.sleep(RESULT_ROWS_READ_RETRY_DELAY_MS * attempt);