diff --git a/servers/boe-server-all/src/main/java/com/xboe/constants/CaseAiConstants.java b/servers/boe-server-all/src/main/java/com/xboe/constants/CaseAiConstants.java index 6190d299..770c70d8 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/constants/CaseAiConstants.java +++ b/servers/boe-server-all/src/main/java/com/xboe/constants/CaseAiConstants.java @@ -3,4 +3,8 @@ package com.xboe.constants; public class CaseAiConstants { public static final String CASE_AI_INDEX_NAME = "ai_chat_messages"; + + public static final String CASE_DOC_UPLOAD_INTERFACE_NAME = "文档上传"; + + public static final String CASE_DOC_DELETE_INTERFACE_NAME = "文档删除"; } diff --git a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseKnowledgeServiceImpl.java b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseKnowledgeServiceImpl.java index c4e2b7a4..9001e40d 100644 --- a/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseKnowledgeServiceImpl.java +++ b/servers/boe-server-all/src/main/java/com/xboe/module/boecase/service/impl/CaseKnowledgeServiceImpl.java @@ -6,6 +6,7 @@ import com.xboe.common.PageList; import com.xboe.common.utils.IDGenerator; import com.xboe.common.utils.StringUtil; import com.xboe.common.OrderCondition; +import com.xboe.constants.CaseAiConstants; import com.xboe.core.CurrentUser; import com.xboe.core.orm.FieldFilters; import com.xboe.core.upload.XFileUploader; @@ -104,7 +105,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { String caseId = cases.getId(); if (cases == null || cases.getDeleted()) { log.error("上传案例文档失败,未找到有效的案例记录,caseId: {}", caseId); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, requestBody.toJSONString(), "上传案例文档失败,未找到有效的案例记录", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; @@ -113,7 +114,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { // 2. 检查文件路径 if (StringUtil.isBlank(cases.getFilePath())) { log.error("上传案例文档失败,案例文件路径为空,caseId: {}", caseId); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, requestBody.toJSONString(), "上传案例文档失败,案例文件路径为空", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; @@ -124,7 +125,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { File file = new File(filePath); if (!file.exists()) { log.error("上传案例文档失败,案例文件不存在,filePath: {}", filePath); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, requestBody.toJSONString(), "上传案例文档失败,案例文件不存在,filePath: " + filePath, CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; @@ -161,7 +162,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { String accessToken = aiAccessTokenService.getAccessToken(); if (StringUtil.isBlank(accessToken)) { log.error("上传案例文档失败,获取access_token失败"); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, requestBody.toJSONString(), "上传案例文档失败,获取access_token失败", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; @@ -189,7 +190,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { String taskId = data.getString("taskId"); // 保存成功的CaseDocumentLog记录 - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, requestBody.toJSONString(), responseBody, CaseDocumentLogRunStatusEnum.RUNNING.getCode(), null, null, taskId); @@ -198,7 +199,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { } else { // 业务处理失败,不重试 log.error("上传案例文档业务处理失败,不重试,response: {}", responseBody); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, requestBody.toJSONString(), responseBody, CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.SUCCESS.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; @@ -206,7 +207,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { } else { // 接口调用失败 log.error("上传案例文档接口调用失败,第{}次尝试,status: {}, response: {}", attempt, statusCode, responseBody); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, requestBody.toJSONString(), responseBody, CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.SUCCESS.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); if (attempt == maxRetries) { @@ -219,7 +220,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { } catch (Exception e) { // 接口调用异常 log.error("上传案例文档接口调用异常,第{}次尝试", attempt, e); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), uploadUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.CREATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, requestBody.toJSONString(), "接口调用异常: " + e.getMessage(), CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); if (attempt == maxRetries) { @@ -253,7 +254,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { String caseId = cases.getId(); if (cases == null) { log.error("删除案例文档失败,未找到案例记录,caseId: {}", caseId); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, "", "删除案例文档失败,未找到案例记录", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; @@ -267,7 +268,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { if (logList.isEmpty()) { log.error("删除案例文档失败,未找到相关的日志记录,caseId: {}", caseId); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, "", "删除案例文档失败,未找到相关的日志记录", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; @@ -277,7 +278,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { String taskId = latestLog.getTaskId(); if (StringUtil.isBlank(taskId)) { log.error("删除案例文档失败,日志记录中taskId为空,caseId: {}", caseId); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, "kId=" + caseAiProperties.getCaseKnowledgeId() + "&taskIds=", "删除案例文档失败,日志记录中taskId为空", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); @@ -291,7 +292,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { String accessToken = aiAccessTokenService.getAccessToken(); if (StringUtil.isBlank(accessToken)) { log.error("删除案例文档失败,获取access_token失败"); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, params, "删除案例文档失败,获取access_token失败", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; @@ -328,7 +329,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { int caseStatus = (deleteSuccess != null && deleteSuccess) ? CaseDocumentLogCaseStatusEnum.SUCCESS.getCode() : CaseDocumentLogCaseStatusEnum.FAILED.getCode(); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, params, responseBody, CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), optStatus, caseStatus, null); @@ -343,7 +344,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { } else { // 业务处理失败,不重试 log.error("删除案例文档业务处理失败,不重试,response: {}", responseBody); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, params, responseBody, CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.SUCCESS.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; @@ -351,7 +352,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { } else { // 接口调用失败 log.error("删除案例文档接口调用失败,第{}次尝试,status: {}, response: {}", attempt, statusCode, responseBody); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, params, responseBody, CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); if (attempt == maxRetries) { @@ -364,7 +365,7 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { } catch (Exception e) { // 接口调用异常 log.error("删除案例文档接口调用异常,第{}次尝试", attempt, e); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), deleteUrl, + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.DELETE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, params, "接口调用异常: " + e.getMessage(), CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); if (attempt == maxRetries) { @@ -393,138 +394,387 @@ public class CaseKnowledgeServiceImpl implements ICaseKnowledgeService { @Override public boolean updateCaseDocument(Cases cases) { - String requestBody = ""; - String requestUrl = caseAiProperties.getBaseUrl() + "/apigateway/knowledge/v1/file/delete"; + String deleteUrl = caseAiProperties.getBaseUrl() + "/apigateway/knowledge/v1/file/delete"; String caseId = cases.getId(); if (cases == null) { - log.error("更新案例文档失败,未找到案例记录,caseId: {}", caseId); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, - requestBody, "更新案例文档失败,未找到案例记录", + log.error("删除案例文档失败,未找到案例记录,caseId: {}", caseId); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, + "", "删除案例文档失败,未找到案例记录", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; } - log.info("开始更新案例文档,caseId: {}", caseId); - - // 获取access_token - String accessToken = aiAccessTokenService.getAccessToken(); - if (StringUtil.isBlank(accessToken)) { - log.error("更新案例文档失败,获取access_token失败"); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, - requestBody, "更新案例文档失败,获取access_token失败", - CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); - return false; - } - - // 1. 根据案例ID查询最新一条CaseDocumentLog数据 + // 2. 根据案例ID查询最新一条CaseDocumentLog数据 List logList = caseDocumentLogDao.getGenericDao() .findList(CaseDocumentLog.class, 1, OrderCondition.desc("sysCreateTime"), FieldFilters.eq("caseId", caseId)); if (logList.isEmpty()) { - log.error("调用删除接口时未找到相关的日志记录,caseId: {}", caseId); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, - requestBody, "调用删除接口时未找到相关的日志记录", + log.error("删除案例文档失败,未找到相关的日志记录,caseId: {}", caseId); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, + "", "删除案例文档失败,未找到相关的日志记录", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; } CaseDocumentLog latestLog = logList.get(0); - String oldTaskId = latestLog.getTaskId(); - if (StringUtil.isBlank(oldTaskId)) { - log.error("调用删除接口时日志记录中taskId为空,caseId: {}", caseId); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, - requestBody, "调用删除接口时日志记录中taskId为空", + String deleteTaskId = latestLog.getTaskId(); + if (StringUtil.isBlank(deleteTaskId)) { + log.error("删除案例文档失败,日志记录中taskId为空,caseId: {}", caseId); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, + "kId=" + caseAiProperties.getCaseKnowledgeId() + + "&taskIds=", "删除案例文档失败,日志记录中taskId为空", + CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); + return false; + } + // 构建请求参数 + String params = "kId=" + caseAiProperties.getCaseKnowledgeId() + + "&taskIds=" + deleteTaskId; + + // 3. 获取access_token + String accessToken = aiAccessTokenService.getAccessToken(); + if (StringUtil.isBlank(accessToken)) { + log.error("删除案例文档失败,获取access_token失败"); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, + params, "删除案例文档失败,获取access_token失败", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; } - try { - // 2. 先调用删除接口 - String deleteParam = "kId=" + caseAiProperties.getCaseKnowledgeId() + "taskId=" + oldTaskId; - requestUrl = caseAiProperties.getBaseUrl() + "/apigateway/knowledge/v1/file/delete?" + deleteParam; - requestBody = deleteParam; - boolean deleteSuccess = callDeleteInterface(caseId, cases, accessToken); - if (!deleteSuccess) { - log.error("更新案例文档失败,删除接口调用失败,不继续执行上传操作,caseId: {}", caseId); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, - deleteParam, "删除接口:失败,上传接口:未执行", + // 4. 重试逻辑:最多3次机会 + int deleteMaxRetries = 3; + for (int attempt = 1; attempt <= deleteMaxRetries; attempt++) { + log.info("删除案例文档第{}次尝试,caseId: {}, taskId: {}", attempt, caseId, deleteTaskId); + + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpDelete httpDelete = new HttpDelete(deleteUrl + "?" + params); + httpDelete.setHeader("X-AI-ApiCode", caseAiProperties.getAiApiCode()); + httpDelete.setHeader("access_token", accessToken); + httpDelete.setHeader("Content-Type", "application/x-www-form-urlencoded"); + + +// StringEntity entity = new StringEntity(params, StandardCharsets.UTF_8); +// entity.setContentType("application/x-www-form-urlencoded"); +// httpDelete.setEntity(entity); + + try (CloseableHttpResponse response = httpClient.execute(httpDelete)) { + int statusCode = response.getStatusLine().getStatusCode(); + String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + + if (statusCode == 200) { + JSONObject result = JSON.parseObject(responseBody); + if (result.getBooleanValue("success")) { + // 接口调用成功,检查业务处理结果 + JSONObject data = result.getJSONObject("data"); + Boolean deleteSuccess = data.getBoolean(deleteTaskId); + + int optStatus = CaseDocumentLogOptStatusEnum.SUCCESS.getCode(); + int caseStatus = (deleteSuccess != null && deleteSuccess) ? + CaseDocumentLogCaseStatusEnum.SUCCESS.getCode() : CaseDocumentLogCaseStatusEnum.FAILED.getCode(); + + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, + params, responseBody, + CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), optStatus, caseStatus, null); + + if (deleteSuccess != null && deleteSuccess) { + log.info("删除案例文档成功,caseId: {}, taskId: {}, 尝试次数: {}", caseId, deleteTaskId, attempt); + return true; + } else { + // 业务处理失败,不重试 + log.error("删除案例文档业务处理失败,不重试,caseId: {}, taskId: {}", caseId, deleteTaskId); + return false; + } + } else { + // 业务处理失败,不重试 + log.error("删除案例文档业务处理失败,不重试,response: {}", responseBody); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, + params, responseBody, + CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.SUCCESS.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); + return false; + } + } else { + // 接口调用失败 + log.error("删除案例文档接口调用失败,第{}次尝试,status: {}, response: {}", attempt, statusCode, responseBody); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, + params, responseBody, + CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); + if (attempt == deleteMaxRetries) { + // 最后一次尝试仍然失败 + return false; + } + // 继续下一次重试 + } + } + } catch (Exception e) { + // 接口调用异常 + log.error("删除案例文档接口调用异常,第{}次尝试", attempt, e); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME, + params, "接口调用异常: " + e.getMessage(), CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); - return false; + if (attempt == deleteMaxRetries) { + // 最后一次尝试仍然异常 + log.error("删除案例文档最终失败,已重试{}次", deleteMaxRetries); + return false; + } + // 继续下一次重试 } + } - // 3. 删除成功后,再调用上传接口 - requestUrl = caseAiProperties.getBaseUrl() + "/apigateway/knowledge/v1/file/upload"; - // 1. 检查文件路径 - if (StringUtil.isBlank(cases.getFilePath())) { - log.error("调用上传接口失败,案例文件路径为空,caseId: {}", caseId); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, - requestBody, "调用上传接口失败,案例文件路径为空", - CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); - return false; - } - - String savePath = fileUploader.getSavePath(); - String filePath = savePath + cases.getFilePath(); - File file = new File(filePath); - if (!file.exists()) { - log.error("调用上传接口失败,案例文件不存在,filePath: {}", filePath); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, - requestBody, "调用上传接口失败,案例文件不存在", - CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); - return false; - } - - // 2. 构建上传参数 - String fileName = cases.getFileName(); - if (StringUtil.isBlank(fileName)) { - fileName = file.getName(); - } - - String fileType = getFileType(fileName); - String userId = getCurrentUserId(); - JSONObject uploadRequestBody = new JSONObject(); - uploadRequestBody.put("userId", userId); - uploadRequestBody.put("kId", caseAiProperties.getCaseKnowledgeId()); - uploadRequestBody.put("fileName", fileName); - uploadRequestBody.put("fileType", fileType); - uploadRequestBody.put("parseType", "AUTO"); - if (caseAiProperties.isFileUploadUseCallback()) { - uploadRequestBody.put("callbackUrl", caseAiProperties.getFileUploadCallbackUrl()); - } - requestBody = uploadRequestBody.toJSONString(); - - String taskId = callUploadInterface(caseId, file, fileName, fileType, userId, accessToken, requestUrl); - boolean uploadSuccess = StringUtil.isNotBlank(taskId); - - // 4. 根据结果保存一条CaseDocumentLog数据 - int runStatus = uploadSuccess ? CaseDocumentLogRunStatusEnum.RUNNING.getCode() : CaseDocumentLogRunStatusEnum.COMPLETED.getCode(); - Integer optStatus = uploadSuccess ? null : CaseDocumentLogOptStatusEnum.SUCCESS.getCode(); - Integer caseStatus = uploadSuccess ? null : CaseDocumentLogCaseStatusEnum.FAILED.getCode(); - String result = String.format("删除接口:成功,上传接口:%s", - uploadSuccess ? "成功" : "失败"); - - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, - requestBody, result, - runStatus, optStatus, caseStatus, taskId); - - if (uploadSuccess) { - log.info("更新案例文档成功,caseId: {}, taskId: {}", caseId, taskId); - } else { - log.error("更新案例文档失败,上传接口调用失败,caseId: {}", caseId); - } - - return uploadSuccess; - - } catch (Exception e) { - log.error("更新案例文档异常", e); - saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), requestUrl, - requestBody, "更新异常: " + e.getMessage(), + JSONObject requestBody = new JSONObject(); + String userId = getCurrentUserId(); + requestBody.put("userId", userId); + requestBody.put("kId", caseAiProperties.getCaseKnowledgeId()); + requestBody.put("parseType", "AUTO"); + // 2. 检查文件路径 + if (StringUtil.isBlank(cases.getFilePath())) { + log.error("上传案例文档失败,案例文件路径为空,caseId: {}", caseId); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, + requestBody.toJSONString(), "上传案例文档失败,案例文件路径为空", CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); return false; } + + String savePath = fileUploader.getSavePath(); + String filePath = savePath + cases.getFilePath(); + File file = new File(filePath); + if (!file.exists()) { + log.error("上传案例文档失败,案例文件不存在,filePath: {}", filePath); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, + requestBody.toJSONString(), "上传案例文档失败,案例文件不存在,filePath: " + filePath, + CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); + return false; + } + + // 4. 构建上传参数 + String fileName = cases.getFileName(); + if (StringUtil.isBlank(fileName)) { + fileName = file.getName(); + } + + String fileType = getFileType(fileName); + + // 5. 重试逻辑:最多3次机会 + int uploadMaxRetries = 3; + + // 构建multipart/form-data请求体 + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.addBinaryBody("file", file); + builder.addTextBody("userId", userId, ContentType.TEXT_PLAIN); + builder.addTextBody("kId", caseAiProperties.getCaseKnowledgeId(), ContentType.TEXT_PLAIN); + builder.addTextBody("fileName", fileName, ContentType.TEXT_PLAIN); + requestBody.put("fileName", fileName); + builder.addTextBody("fileType", fileType, ContentType.TEXT_PLAIN); + requestBody.put("fileType", fileType); + builder.addTextBody("parseType", "AUTO", ContentType.TEXT_PLAIN); + // 由于接口权限,目前采用不回调,而是通过批处理的方式,处理文件状态 + if (caseAiProperties.isFileUploadUseCallback()) { + builder.addTextBody("callbackUrl", caseAiProperties.getFileUploadCallbackUrl(), ContentType.TEXT_PLAIN); + requestBody.put("callbackUrl", caseAiProperties.getFileUploadCallbackUrl()); + } + + String uploadUrl = caseAiProperties.getBaseUrl() + "/apigateway/knowledge/v1/file/upload"; + for (int attempt = 1; attempt <= uploadMaxRetries; attempt++) { + log.info("上传案例文档第{}次尝试,caseId: {}", attempt, caseId); + + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpPost httpPost = new HttpPost(uploadUrl); + httpPost.setHeader("X-AI-ApiCode", caseAiProperties.getAiApiCode()); + httpPost.setHeader("access_token", accessToken); + + HttpEntity multipart = builder.build(); + httpPost.setEntity(multipart); + + try (CloseableHttpResponse response = httpClient.execute(httpPost)) { + int statusCode = response.getStatusLine().getStatusCode(); + String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + + if (statusCode == 200) { + JSONObject result = JSON.parseObject(responseBody); + if (result.getBooleanValue("success")) { + // 业务处理成功 + JSONObject data = result.getJSONObject("data"); + String taskId = data.getString("taskId"); + + // 保存成功的CaseDocumentLog记录 + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, + requestBody.toJSONString(), responseBody, + CaseDocumentLogRunStatusEnum.RUNNING.getCode(), null, null, taskId); + + log.info("上传案例文档成功,等待文档状态变更. caseId: {}, taskId: {}, 尝试次数: {}", caseId, taskId, attempt); + return true; + } else { + // 业务处理失败,不重试 + log.error("上传案例文档业务处理失败,不重试,response: {}", responseBody); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, + requestBody.toJSONString(), responseBody, + CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.SUCCESS.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); + return false; + } + } else { + // 接口调用失败 + log.error("上传案例文档接口调用失败,第{}次尝试,status: {}, response: {}", attempt, statusCode, responseBody); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, + requestBody.toJSONString(), responseBody, + CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.SUCCESS.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); + if (attempt == uploadMaxRetries) { + // 最后一次尝试仍然失败 + return false; + } + // 继续下一次重试 + } + } + } catch (Exception e) { + // 接口调用异常 + log.error("上传案例文档接口调用异常,第{}次尝试", attempt, e); + saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME, + requestBody.toJSONString(), "接口调用异常: " + e.getMessage(), + CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); + if (attempt == uploadMaxRetries) { + // 最后一次尝试仍然异常 + log.error("上传案例文档最终失败,已重试{}次", uploadMaxRetries); + return false; + } + // 继续下一次重试 + } + } + + return false; +// String requestBody = ""; +// String requestUrl = caseAiProperties.getBaseUrl() + "/apigateway/knowledge/v1/file/delete"; +// String interfaceName = CaseAiConstants.CASE_DOC_DELETE_INTERFACE_NAME; +// +// String caseId = cases.getId(); +// if (cases == null) { +// log.error("更新案例文档失败,未找到案例记录,caseId: {}", caseId); +// saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), interfaceName, +// requestBody, "更新案例文档失败,未找到案例记录", +// CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); +// return false; +// } +// +// log.info("开始更新案例文档,caseId: {}", caseId); +// +// // 获取access_token +// String accessToken = aiAccessTokenService.getAccessToken(); +// if (StringUtil.isBlank(accessToken)) { +// log.error("更新案例文档失败,获取access_token失败"); +// saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), interfaceName, +// requestBody, "更新案例文档失败,获取access_token失败", +// CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); +// return false; +// } +// +// // 1. 根据案例ID查询最新一条CaseDocumentLog数据 +// List logList = caseDocumentLogDao.getGenericDao() +// .findList(CaseDocumentLog.class, 1, +// OrderCondition.desc("sysCreateTime"), +// FieldFilters.eq("caseId", caseId)); +// +// if (logList.isEmpty()) { +// log.error("调用删除接口时未找到相关的日志记录,caseId: {}", caseId); +// saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), interfaceName, +// requestBody, "调用删除接口时未找到相关的日志记录", +// CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); +// return false; +// } +// +// CaseDocumentLog latestLog = logList.get(0); +// String oldTaskId = latestLog.getTaskId(); +// if (StringUtil.isBlank(oldTaskId)) { +// log.error("调用删除接口时日志记录中taskId为空,caseId: {}", caseId); +// saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), interfaceName, +// requestBody, "调用删除接口时日志记录中taskId为空", +// CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); +// return false; +// } +// +// try { +// // 2. 先调用删除接口 +// String deleteParam = "kId=" + caseAiProperties.getCaseKnowledgeId() + "taskId=" + oldTaskId; +// requestUrl = caseAiProperties.getBaseUrl() + "/apigateway/knowledge/v1/file/delete?" + deleteParam; +// requestBody = deleteParam; +// boolean deleteSuccess = callDeleteInterface(caseId, cases, accessToken); +// if (!deleteSuccess) { +// log.error("更新案例文档失败,删除接口调用失败,不继续执行上传操作,caseId: {}", caseId); +// saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), interfaceName, +// deleteParam, "删除接口:失败,上传接口:未执行", +// CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); +// return false; +// } +// +// // 3. 删除成功后,再调用上传接口 +// requestUrl = caseAiProperties.getBaseUrl() + "/apigateway/knowledge/v1/file/upload"; +// interfaceName = CaseAiConstants.CASE_DOC_UPLOAD_INTERFACE_NAME; +// // 1. 检查文件路径 +// if (StringUtil.isBlank(cases.getFilePath())) { +// log.error("调用上传接口失败,案例文件路径为空,caseId: {}", caseId); +// saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), interfaceName, +// requestBody, "调用上传接口失败,案例文件路径为空", +// CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); +// return false; +// } +// +// String savePath = fileUploader.getSavePath(); +// String filePath = savePath + cases.getFilePath(); +// File file = new File(filePath); +// if (!file.exists()) { +// log.error("调用上传接口失败,案例文件不存在,filePath: {}", filePath); +// saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), interfaceName, +// requestBody, "调用上传接口失败,案例文件不存在", +// CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); +// return false; +// } +// +// // 2. 构建上传参数 +// String fileName = cases.getFileName(); +// if (StringUtil.isBlank(fileName)) { +// fileName = file.getName(); +// } +// +// String fileType = getFileType(fileName); +// String userId = getCurrentUserId(); +// JSONObject uploadRequestBody = new JSONObject(); +// uploadRequestBody.put("userId", userId); +// uploadRequestBody.put("kId", caseAiProperties.getCaseKnowledgeId()); +// uploadRequestBody.put("fileName", fileName); +// uploadRequestBody.put("fileType", fileType); +// uploadRequestBody.put("parseType", "AUTO"); +// if (caseAiProperties.isFileUploadUseCallback()) { +// uploadRequestBody.put("callbackUrl", caseAiProperties.getFileUploadCallbackUrl()); +// } +// requestBody = uploadRequestBody.toJSONString(); +// +// String taskId = callUploadInterface(caseId, file, fileName, fileType, userId, accessToken, requestUrl); +// boolean uploadSuccess = StringUtil.isNotBlank(taskId); +// +// // 4. 根据结果保存一条CaseDocumentLog数据 +// int runStatus = uploadSuccess ? CaseDocumentLogRunStatusEnum.RUNNING.getCode() : CaseDocumentLogRunStatusEnum.COMPLETED.getCode(); +// Integer optStatus = uploadSuccess ? null : CaseDocumentLogOptStatusEnum.SUCCESS.getCode(); +// Integer caseStatus = uploadSuccess ? null : CaseDocumentLogCaseStatusEnum.FAILED.getCode(); +// String result = String.format("删除接口:成功,上传接口:%s", +// uploadSuccess ? "成功" : "失败"); +// +// saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), interfaceName, +// requestBody, result, +// runStatus, optStatus, caseStatus, taskId); +// +// if (uploadSuccess) { +// log.info("更新案例文档成功,caseId: {}, taskId: {}", caseId, taskId); +// } else { +// log.error("更新案例文档失败,上传接口调用失败,caseId: {}", caseId); +// } +// +// return uploadSuccess; +// +// } catch (Exception e) { +// log.error("更新案例文档异常", e); +// saveCaseDocumentLog(caseId, cases.getTitle(), CaseDocumentLogOptTypeEnum.UPDATE.getCode(), interfaceName, +// requestBody, "更新异常: " + e.getMessage(), +// CaseDocumentLogRunStatusEnum.COMPLETED.getCode(), CaseDocumentLogOptStatusEnum.FAILED.getCode(), CaseDocumentLogCaseStatusEnum.FAILED.getCode(), null); +// return false; +// } } @Override