fix(ccdi-project): truncate upload error messages
This commit is contained in:
@@ -50,6 +50,8 @@ import java.util.concurrent.RejectedExecutionException;
|
||||
@Service
|
||||
public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
|
||||
|
||||
private static final int MAX_ERROR_MESSAGE_LENGTH = 2000;
|
||||
|
||||
@Data
|
||||
private static class FetchBankStatementResult {
|
||||
private boolean success;
|
||||
@@ -330,10 +332,26 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
|
||||
CcdiFileUploadRecord record = new CcdiFileUploadRecord();
|
||||
record.setId(recordId);
|
||||
record.setFileStatus(status);
|
||||
record.setErrorMessage(errorMessage);
|
||||
record.setErrorMessage(normalizeErrorMessage(errorMessage));
|
||||
recordMapper.updateById(record);
|
||||
}
|
||||
|
||||
private void updateFailedRecord(CcdiFileUploadRecord record, String errorMessage) {
|
||||
record.setFileStatus("parsed_failed");
|
||||
record.setErrorMessage(normalizeErrorMessage(errorMessage));
|
||||
recordMapper.updateById(record);
|
||||
}
|
||||
|
||||
private String normalizeErrorMessage(String errorMessage) {
|
||||
if (!StringUtils.hasText(errorMessage)) {
|
||||
return null;
|
||||
}
|
||||
if (errorMessage.length() <= MAX_ERROR_MESSAGE_LENGTH) {
|
||||
return errorMessage;
|
||||
}
|
||||
return errorMessage.substring(0, MAX_ERROR_MESSAGE_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步处理单个文件的完整流程
|
||||
* 包含:上传 → 轮询解析状态 → 获取结果 → 保存流水数据
|
||||
@@ -444,9 +462,7 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
|
||||
FetchBankStatementResult fetchResult =
|
||||
fetchAndSaveBankStatements(projectId, lsfxProjectId, logId);
|
||||
if (!fetchResult.isSuccess()) {
|
||||
record.setFileStatus("parsed_failed");
|
||||
record.setErrorMessage(fetchResult.getErrorMessage());
|
||||
recordMapper.updateById(record);
|
||||
updateFailedRecord(record, fetchResult.getErrorMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -459,9 +475,7 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
|
||||
} else {
|
||||
// 解析失败
|
||||
log.warn("【文件上传】步骤6: 解析失败: status={}, desc={}", status, uploadStatusDesc);
|
||||
record.setFileStatus("parsed_failed");
|
||||
record.setErrorMessage("解析失败: " + uploadStatusDesc);
|
||||
recordMapper.updateById(record);
|
||||
updateFailedRecord(record, "解析失败: " + uploadStatusDesc);
|
||||
}
|
||||
|
||||
log.info("【文件上传】处理完成: fileName={}", record.getFileName());
|
||||
|
||||
@@ -39,6 +39,7 @@ class CcdiFileUploadServiceImplTest {
|
||||
private static final Integer LSFX_PROJECT_ID = 200;
|
||||
private static final Long RECORD_ID = 300L;
|
||||
private static final Integer LOG_ID = 400;
|
||||
private static final int MAX_ERROR_MESSAGE_LENGTH = 2000;
|
||||
|
||||
@InjectMocks
|
||||
private CcdiFileUploadServiceImpl service;
|
||||
@@ -148,6 +149,44 @@ class CcdiFileUploadServiceImplTest {
|
||||
verify(bankStatementMapper).deleteByProjectIdAndBatchId(PROJECT_ID, LOG_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
void processFileAsync_shouldTruncateLongErrorMessageWhenBankStatementFetchFails() throws IOException {
|
||||
List<CcdiFileUploadRecord> updates = new ArrayList<>();
|
||||
captureUpdatedRecords(updates);
|
||||
|
||||
when(lsfxClient.uploadFile(eq(LSFX_PROJECT_ID), any())).thenReturn(buildUploadResponse());
|
||||
when(lsfxClient.checkParseStatus(LSFX_PROJECT_ID, String.valueOf(LOG_ID)))
|
||||
.thenReturn(buildCheckParseStatusResponse(false));
|
||||
when(lsfxClient.getFileUploadStatus(any())).thenReturn(buildParsedSuccessStatusResponse());
|
||||
when(lsfxClient.getBankStatement(any(GetBankStatementRequest.class)))
|
||||
.thenThrow(new RuntimeException("bank statement fetch failed:" + "x".repeat(3000)));
|
||||
|
||||
CcdiFileUploadRecord record = buildRecord();
|
||||
Path tempFile = createTempFile();
|
||||
|
||||
service.processFileAsync(PROJECT_ID, LSFX_PROJECT_ID, tempFile.toString(), RECORD_ID, "batch-1", record);
|
||||
|
||||
CcdiFileUploadRecord failedRecord = findLastUpdatedRecordByStatus(updates, "parsed_failed");
|
||||
assertTrue(failedRecord.getErrorMessage().length() <= MAX_ERROR_MESSAGE_LENGTH);
|
||||
}
|
||||
|
||||
@Test
|
||||
void processFileAsync_shouldTruncateLongErrorMessageWhenUnexpectedFailureOccurs() throws IOException {
|
||||
List<CcdiFileUploadRecord> updates = new ArrayList<>();
|
||||
captureUpdatedRecords(updates);
|
||||
|
||||
when(lsfxClient.uploadFile(eq(LSFX_PROJECT_ID), any()))
|
||||
.thenThrow(new RuntimeException("upload failed:" + "x".repeat(3000)));
|
||||
|
||||
CcdiFileUploadRecord record = buildRecord();
|
||||
Path tempFile = createTempFile();
|
||||
|
||||
service.processFileAsync(PROJECT_ID, LSFX_PROJECT_ID, tempFile.toString(), RECORD_ID, "batch-1", record);
|
||||
|
||||
CcdiFileUploadRecord failedRecord = findLastUpdatedRecordByStatus(updates, "parsed_failed");
|
||||
assertTrue(failedRecord.getErrorMessage().length() <= MAX_ERROR_MESSAGE_LENGTH);
|
||||
}
|
||||
|
||||
private void captureRecordStatus(List<String> events, AtomicInteger sequence) {
|
||||
doAnswer(invocation -> {
|
||||
CcdiFileUploadRecord record = invocation.getArgument(0);
|
||||
@@ -156,6 +195,18 @@ class CcdiFileUploadServiceImplTest {
|
||||
}).when(recordMapper).updateById(any(CcdiFileUploadRecord.class));
|
||||
}
|
||||
|
||||
private void captureUpdatedRecords(List<CcdiFileUploadRecord> updates) {
|
||||
doAnswer(invocation -> {
|
||||
CcdiFileUploadRecord record = invocation.getArgument(0);
|
||||
CcdiFileUploadRecord snapshot = new CcdiFileUploadRecord();
|
||||
snapshot.setId(record.getId());
|
||||
snapshot.setFileStatus(record.getFileStatus());
|
||||
snapshot.setErrorMessage(record.getErrorMessage());
|
||||
updates.add(snapshot);
|
||||
return 1;
|
||||
}).when(recordMapper).updateById(any(CcdiFileUploadRecord.class));
|
||||
}
|
||||
|
||||
private CcdiFileUploadRecord buildRecord() {
|
||||
CcdiFileUploadRecord record = new CcdiFileUploadRecord();
|
||||
record.setId(RECORD_ID);
|
||||
@@ -236,4 +287,14 @@ class CcdiFileUploadServiceImplTest {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private CcdiFileUploadRecord findLastUpdatedRecordByStatus(List<CcdiFileUploadRecord> updates,
|
||||
String status) {
|
||||
for (int i = updates.size() - 1; i >= 0; i--) {
|
||||
if (status.equals(updates.get(i).getFileStatus())) {
|
||||
return updates.get(i);
|
||||
}
|
||||
}
|
||||
throw new AssertionError("未找到状态为 " + status + " 的更新记录");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user