From 82624affb0251b75b62b35567d3eb260c06efe78 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期一, 23 三月 2026 12:48:07 +0800
Subject: [PATCH] #ai 代码优化
---
rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiMcpMountServiceImpl.java | 262 ++++++++++++++++++----------------------------------
1 files changed, 90 insertions(+), 172 deletions(-)
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiMcpMountServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiMcpMountServiceImpl.java
index 87eb622..8c96030 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiMcpMountServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiMcpMountServiceImpl.java
@@ -1,9 +1,7 @@
package com.vincent.rsf.server.ai.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.ai.config.AiDefaults;
import com.vincent.rsf.server.ai.dto.AiMcpConnectivityTestDto;
@@ -12,30 +10,30 @@
import com.vincent.rsf.server.ai.dto.AiMcpToolTestRequest;
import com.vincent.rsf.server.ai.entity.AiMcpMount;
import com.vincent.rsf.server.ai.mapper.AiMcpMountMapper;
+import com.vincent.rsf.server.ai.service.impl.mcp.AiMcpAdminService;
+import com.vincent.rsf.server.ai.store.AiConfigCacheStore;
+import com.vincent.rsf.server.ai.store.AiConversationCacheStore;
+import com.vincent.rsf.server.ai.store.AiMcpCacheStore;
import com.vincent.rsf.server.ai.service.AiMcpMountService;
import com.vincent.rsf.server.ai.service.BuiltinMcpToolRegistry;
-import com.vincent.rsf.server.ai.service.McpMountRuntimeFactory;
import com.vincent.rsf.server.system.enums.StatusType;
import lombok.RequiredArgsConstructor;
-import org.springframework.ai.chat.model.ToolContext;
-import org.springframework.ai.tool.ToolCallback;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
import java.util.List;
-import java.util.Map;
@Service("aiMcpMountService")
@RequiredArgsConstructor
public class AiMcpMountServiceImpl extends ServiceImpl<AiMcpMountMapper, AiMcpMount> implements AiMcpMountService {
private final BuiltinMcpToolRegistry builtinMcpToolRegistry;
- private final McpMountRuntimeFactory mcpMountRuntimeFactory;
- private final ObjectMapper objectMapper;
+ private final AiMcpAdminService aiMcpAdminService;
+ private final AiMcpCacheStore aiMcpCacheStore;
+ private final AiConfigCacheStore aiConfigCacheStore;
+ private final AiConversationCacheStore aiConversationCacheStore;
+ /** 鏌ヨ鏌愪釜绉熸埛涓嬪綋鍓嶅惎鐢ㄧ殑 MCP 鎸傝浇鍒楄〃銆� */
@Override
public List<AiMcpMount> listActiveMounts(Long tenantId) {
ensureTenantId(tenantId);
@@ -47,6 +45,7 @@
.orderByAsc(AiMcpMount::getId));
}
+ /** 淇濆瓨鍓嶆牎楠� MCP 鎸傝浇鑽夌锛屽苟琛ュ叏杩愯鏃堕粯璁ゅ�笺�� */
@Override
public void validateBeforeSave(AiMcpMount aiMcpMount, Long tenantId) {
ensureTenantId(tenantId);
@@ -55,6 +54,7 @@
ensureRequiredFields(aiMcpMount, tenantId);
}
+ /** 鏇存柊鍓嶆牎楠屽苟閿佸畾璁板綍鎵�灞炵鎴凤紝闃叉璺ㄧ鎴蜂慨鏀广�� */
@Override
public void validateBeforeUpdate(AiMcpMount aiMcpMount, Long tenantId) {
ensureTenantId(tenantId);
@@ -62,117 +62,98 @@
if (aiMcpMount.getId() == null) {
throw new CoolException("MCP 鎸傝浇 ID 涓嶈兘涓虹┖");
}
- AiMcpMount current = requireMount(aiMcpMount.getId(), tenantId);
+ AiMcpMount current = aiMcpAdminService.requireMount(aiMcpMount.getId(), tenantId);
aiMcpMount.setTenantId(current.getTenantId());
ensureRequiredFields(aiMcpMount, tenantId);
}
+ /**
+ * 棰勮褰撳墠鎸傝浇鏈�缁堜細鏆撮湶缁欐ā鍨嬬殑宸ュ叿鐩綍銆�
+ * 瀵瑰唴缃� MCP 浼氶澶栧悎骞舵不鐞嗙洰褰曚俊鎭紝瀵瑰閮� MCP 鍒欎互瀹為檯瑙f瀽缁撴灉涓哄噯銆�
+ */
@Override
public List<AiMcpToolPreviewDto> previewTools(Long mountId, Long userId, Long tenantId) {
- AiMcpMount mount = requireMount(mountId, tenantId);
- long startedAt = System.currentTimeMillis();
- try (McpMountRuntimeFactory.McpMountRuntime runtime = mcpMountRuntimeFactory.create(List.of(mount), userId)) {
- List<AiMcpToolPreviewDto> tools = buildToolPreviewDtos(runtime.getToolCallbacks(),
- AiDefaults.MCP_TRANSPORT_BUILTIN.equals(mount.getTransportType())
- ? builtinMcpToolRegistry.listBuiltinToolCatalog(mount.getBuiltinCode())
- : List.of());
- if (!runtime.getErrors().isEmpty()) {
- String message = String.join("锛�", runtime.getErrors());
- updateHealthStatus(mount.getId(), AiDefaults.MCP_HEALTH_UNHEALTHY, message, System.currentTimeMillis() - startedAt);
- throw new CoolException(message);
- }
- updateHealthStatus(mount.getId(), AiDefaults.MCP_HEALTH_HEALTHY,
- "宸ュ叿瑙f瀽鎴愬姛锛屽叡 " + tools.size() + " 涓伐鍏�", System.currentTimeMillis() - startedAt);
- return tools;
- } catch (CoolException e) {
- throw e;
- } catch (Exception e) {
- updateHealthStatus(mount.getId(), AiDefaults.MCP_HEALTH_UNHEALTHY,
- "宸ュ叿瑙f瀽澶辫触: " + e.getMessage(), System.currentTimeMillis() - startedAt);
- throw new CoolException("鑾峰彇宸ュ叿鍒楄〃澶辫触: " + e.getMessage());
+ AiMcpMount mount = aiMcpAdminService.requireMount(mountId, tenantId);
+ List<AiMcpToolPreviewDto> cached = aiMcpCacheStore.getToolPreview(tenantId, mountId);
+ if (cached != null) {
+ return cached;
}
+ List<AiMcpToolPreviewDto> tools = aiMcpAdminService.previewTools(mount, userId);
+ aiMcpCacheStore.cacheToolPreview(tenantId, mountId, tools);
+ return tools;
}
+ /** 瀵瑰凡淇濆瓨鐨勬寕杞藉仛鐪熷疄杩為�氭�ф祴璇曪紝骞舵妸缁撴灉鍥炲啓鍒拌繍琛屾�佸瓧娈点�� */
@Override
public AiMcpConnectivityTestDto testConnectivity(Long mountId, Long userId, Long tenantId) {
- AiMcpMount mount = requireMount(mountId, tenantId);
- long startedAt = System.currentTimeMillis();
- try (McpMountRuntimeFactory.McpMountRuntime runtime = mcpMountRuntimeFactory.create(List.of(mount), userId)) {
- long elapsedMs = System.currentTimeMillis() - startedAt;
- if (!runtime.getErrors().isEmpty()) {
- String message = String.join("锛�", runtime.getErrors());
- updateHealthStatus(mount.getId(), AiDefaults.MCP_HEALTH_UNHEALTHY, message, elapsedMs);
- AiMcpMount latest = requireMount(mount.getId(), tenantId);
- return buildConnectivityDto(latest, message, elapsedMs, runtime.getToolCallbacks().length);
- }
- String message = "杩為�氭�ф祴璇曟垚鍔燂紝瑙f瀽鍑� " + runtime.getToolCallbacks().length + " 涓伐鍏�";
- updateHealthStatus(mount.getId(), AiDefaults.MCP_HEALTH_HEALTHY, message, elapsedMs);
- AiMcpMount latest = requireMount(mount.getId(), tenantId);
- return buildConnectivityDto(latest, message, elapsedMs, runtime.getToolCallbacks().length);
- } catch (CoolException e) {
- throw e;
- } catch (Exception e) {
- long elapsedMs = System.currentTimeMillis() - startedAt;
- String message = "杩為�氭�ф祴璇曞け璐�: " + e.getMessage();
- updateHealthStatus(mount.getId(), AiDefaults.MCP_HEALTH_UNHEALTHY, message, elapsedMs);
- AiMcpMount latest = requireMount(mount.getId(), tenantId);
- return buildConnectivityDto(latest, message, elapsedMs, 0);
- }
+ AiMcpMount mount = aiMcpAdminService.requireMount(mountId, tenantId);
+ AiMcpConnectivityTestDto connectivity = aiMcpAdminService.testConnectivity(mount, userId, true);
+ aiMcpCacheStore.cacheConnectivity(tenantId, mountId, connectivity);
+ return connectivity;
}
+ /** 瀵硅〃鍗曢噷鐨勮崏绋块厤缃仛涓存椂杩為�氭�ф祴璇曪紝涓嶈惤搴撱�� */
@Override
- public AiMcpToolTestDto testTool(Long mountId, Long userId, Long tenantId, AiMcpToolTestRequest request) {
+ public AiMcpConnectivityTestDto testDraftConnectivity(AiMcpMount mount, Long userId, Long tenantId) {
+ ensureTenantId(tenantId);
if (userId == null) {
throw new CoolException("褰撳墠鐧诲綍鐢ㄦ埛涓嶅瓨鍦�");
}
- if (tenantId == null) {
- throw new CoolException("褰撳墠绉熸埛涓嶅瓨鍦�");
+ if (mount == null) {
+ throw new CoolException("MCP 鎸傝浇鍙傛暟涓嶈兘涓虹┖");
}
- if (request == null) {
- throw new CoolException("宸ュ叿娴嬭瘯鍙傛暟涓嶈兘涓虹┖");
+ mount.setTenantId(tenantId);
+ fillDefaults(mount);
+ ensureRequiredFields(mount, tenantId);
+ return aiMcpAdminService.testConnectivity(mount, userId, false);
+ }
+
+ /**
+ * 鐩存帴鎵ц鏌愪竴涓伐鍏风殑娴嬭瘯璋冪敤銆�
+ * 璇ユ柟娉曚富瑕佹湇鍔′簬绠$悊绔殑鈥滃伐鍏锋祴璇曗�濋潰鏉匡紝涓嶅弬涓庢寮忓璇濋摼璺��
+ */
+ @Override
+ public AiMcpToolTestDto testTool(Long mountId, Long userId, Long tenantId, AiMcpToolTestRequest request) {
+ AiMcpMount mount = aiMcpAdminService.requireMount(mountId, tenantId);
+ return aiMcpAdminService.testTool(mount, userId, tenantId, request);
+ }
+
+ @Override
+ public boolean save(AiMcpMount entity) {
+ boolean saved = super.save(entity);
+ if (saved && entity != null && entity.getTenantId() != null) {
+ evictMountRelatedCaches(entity.getTenantId(), entity.getId());
}
- if (!StringUtils.hasText(request.getToolName())) {
- throw new CoolException("宸ュ叿鍚嶇О涓嶈兘涓虹┖");
+ return saved;
+ }
+
+ @Override
+ public boolean updateById(AiMcpMount entity) {
+ boolean updated = super.updateById(entity);
+ if (updated && entity != null && entity.getTenantId() != null) {
+ evictMountRelatedCaches(entity.getTenantId(), entity.getId());
}
- if (!StringUtils.hasText(request.getInputJson())) {
- throw new CoolException("宸ュ叿杈撳叆 JSON 涓嶈兘涓虹┖");
+ return updated;
+ }
+
+ @Override
+ public boolean removeByIds(java.util.Collection<?> list) {
+ java.util.List<java.io.Serializable> ids = list == null ? java.util.List.of() : list.stream()
+ .filter(java.util.Objects::nonNull)
+ .map(item -> (java.io.Serializable) item)
+ .toList();
+ java.util.List<AiMcpMount> records = this.listByIds(ids);
+ boolean removed = super.removeByIds(list);
+ if (removed) {
+ records.stream()
+ .filter(java.util.Objects::nonNull)
+ .forEach(item -> evictMountRelatedCaches(item.getTenantId(), item.getId()));
}
- try {
- objectMapper.readTree(request.getInputJson());
- } catch (Exception e) {
- throw new CoolException("宸ュ叿杈撳叆 JSON 鏍煎紡閿欒: " + e.getMessage());
- }
- AiMcpMount mount = requireMount(mountId, tenantId);
- long startedAt = System.currentTimeMillis();
- try (McpMountRuntimeFactory.McpMountRuntime runtime = mcpMountRuntimeFactory.create(List.of(mount), userId)) {
- ToolCallback callback = Arrays.stream(runtime.getToolCallbacks())
- .filter(item -> item != null && item.getToolDefinition() != null)
- .filter(item -> request.getToolName().equals(item.getToolDefinition().name()))
- .findFirst()
- .orElseThrow(() -> new CoolException("鏈壘鍒拌娴嬭瘯鐨勫伐鍏�: " + request.getToolName()));
- String output = callback.call(
- request.getInputJson(),
- new ToolContext(Map.of("userId", userId, "tenantId", tenantId, "mountId", mountId))
- );
- updateHealthStatus(mount.getId(), AiDefaults.MCP_HEALTH_HEALTHY,
- "宸ュ叿娴嬭瘯鎴愬姛: " + request.getToolName(), System.currentTimeMillis() - startedAt);
- return AiMcpToolTestDto.builder()
- .toolName(request.getToolName())
- .inputJson(request.getInputJson())
- .output(output)
- .build();
- } catch (CoolException e) {
- updateHealthStatus(mount.getId(), AiDefaults.MCP_HEALTH_UNHEALTHY,
- "宸ュ叿娴嬭瘯澶辫触: " + e.getMessage(), System.currentTimeMillis() - startedAt);
- throw e;
- } catch (Exception e) {
- updateHealthStatus(mount.getId(), AiDefaults.MCP_HEALTH_UNHEALTHY,
- "宸ュ叿娴嬭瘯澶辫触: " + e.getMessage(), System.currentTimeMillis() - startedAt);
- throw new CoolException("宸ュ叿娴嬭瘯澶辫触: " + e.getMessage());
- }
+ return removed;
}
private void fillDefaults(AiMcpMount aiMcpMount) {
+ /** 涓烘寕杞借崏绋胯ˉ榻愮粺涓�榛樿鍊硷紝淇濊瘉鍚庣画杩愯鏃朵唬鐮佷笉闇�瑕侀噸澶嶅垽鏂┖鍊笺�� */
if (!StringUtils.hasText(aiMcpMount.getTransportType())) {
aiMcpMount.setTransportType(AiDefaults.MCP_TRANSPORT_SSE_HTTP);
}
@@ -191,6 +172,10 @@
}
private void ensureRequiredFields(AiMcpMount aiMcpMount, Long tenantId) {
+ /**
+ * 鎸� transportType 鏍¢獙鎸傝浇蹇呭~椤广��
+ * 杩欓噷鎶娾�滃瓧娈靛悎娉曟�р�濆拰鈥滆法璁板綍鍐茬獊鈥濅竴璧锋敹鍙o紝閬垮厤鏍¢獙閫昏緫鍒嗘暎鍦� controller 灞傘��
+ */
if (!StringUtils.hasText(aiMcpMount.getName())) {
throw new CoolException("MCP 鎸傝浇鍚嶇О涓嶈兘涓虹┖");
}
@@ -214,23 +199,8 @@
throw new CoolException("涓嶆敮鎸佺殑 MCP 浼犺緭绫诲瀷: " + aiMcpMount.getTransportType());
}
- private AiMcpMount requireMount(Long mountId, Long tenantId) {
- ensureTenantId(tenantId);
- if (mountId == null) {
- throw new CoolException("MCP 鎸傝浇 ID 涓嶈兘涓虹┖");
- }
- AiMcpMount mount = this.getOne(new LambdaQueryWrapper<AiMcpMount>()
- .eq(AiMcpMount::getId, mountId)
- .eq(AiMcpMount::getTenantId, tenantId)
- .eq(AiMcpMount::getDeleted, 0)
- .last("limit 1"));
- if (mount == null) {
- throw new CoolException("MCP 鎸傝浇涓嶅瓨鍦�");
- }
- return mount;
- }
-
private void ensureBuiltinConflictFree(AiMcpMount aiMcpMount, Long tenantId) {
+ /** 鏍¢獙鍚岀鎴蜂笅鏄惁瀛樺湪涓庡綋鍓嶅唴缃紪鐮佷簰鏂ョ殑鍚敤鎸傝浇銆� */
if (aiMcpMount.getStatus() == null || aiMcpMount.getStatus() != StatusType.ENABLE.val) {
return;
}
@@ -256,19 +226,10 @@
}
private List<String> resolveConflictCodes(String builtinCode) {
- List<String> codes = new ArrayList<>();
if (AiDefaults.MCP_BUILTIN_RSF_WMS.equals(builtinCode)) {
- codes.add(AiDefaults.MCP_BUILTIN_RSF_WMS_STOCK);
- codes.add(AiDefaults.MCP_BUILTIN_RSF_WMS_TASK);
- codes.add(AiDefaults.MCP_BUILTIN_RSF_WMS_BASE);
- return codes;
+ return List.of();
}
- if (AiDefaults.MCP_BUILTIN_RSF_WMS_STOCK.equals(builtinCode)
- || AiDefaults.MCP_BUILTIN_RSF_WMS_TASK.equals(builtinCode)
- || AiDefaults.MCP_BUILTIN_RSF_WMS_BASE.equals(builtinCode)) {
- codes.add(AiDefaults.MCP_BUILTIN_RSF_WMS);
- }
- return codes;
+ throw new CoolException("涓嶆敮鎸佺殑鍐呯疆 MCP 缂栫爜: " + builtinCode);
}
private void ensureTenantId(Long tenantId) {
@@ -277,52 +238,9 @@
}
}
- private List<AiMcpToolPreviewDto> buildToolPreviewDtos(ToolCallback[] callbacks, List<AiMcpToolPreviewDto> governedCatalog) {
- List<AiMcpToolPreviewDto> tools = new ArrayList<>();
- Map<String, AiMcpToolPreviewDto> catalogMap = new java.util.LinkedHashMap<>();
- for (AiMcpToolPreviewDto item : governedCatalog) {
- if (item == null || !StringUtils.hasText(item.getName())) {
- continue;
- }
- catalogMap.put(item.getName(), item);
- }
- for (ToolCallback callback : callbacks) {
- if (callback == null || callback.getToolDefinition() == null) {
- continue;
- }
- AiMcpToolPreviewDto governedItem = catalogMap.get(callback.getToolDefinition().name());
- tools.add(AiMcpToolPreviewDto.builder()
- .name(callback.getToolDefinition().name())
- .description(callback.getToolDefinition().description())
- .inputSchema(callback.getToolDefinition().inputSchema())
- .returnDirect(callback.getToolMetadata() == null ? null : callback.getToolMetadata().returnDirect())
- .toolGroup(governedItem == null ? null : governedItem.getToolGroup())
- .toolPurpose(governedItem == null ? null : governedItem.getToolPurpose())
- .queryBoundary(governedItem == null ? null : governedItem.getQueryBoundary())
- .exampleQuestions(governedItem == null ? List.of() : governedItem.getExampleQuestions())
- .build());
- }
- return tools;
- }
-
- private void updateHealthStatus(Long mountId, String healthStatus, String message, Long initElapsedMs) {
- this.update(new LambdaUpdateWrapper<AiMcpMount>()
- .eq(AiMcpMount::getId, mountId)
- .set(AiMcpMount::getHealthStatus, healthStatus)
- .set(AiMcpMount::getLastTestTime, new Date())
- .set(AiMcpMount::getLastTestMessage, message)
- .set(AiMcpMount::getLastInitElapsedMs, initElapsedMs));
- }
-
- private AiMcpConnectivityTestDto buildConnectivityDto(AiMcpMount mount, String message, Long initElapsedMs, Integer toolCount) {
- return AiMcpConnectivityTestDto.builder()
- .mountId(mount.getId())
- .mountName(mount.getName())
- .healthStatus(mount.getHealthStatus())
- .message(message)
- .initElapsedMs(initElapsedMs)
- .toolCount(toolCount)
- .testedAt(mount.getLastTestTime$())
- .build();
+ private void evictMountRelatedCaches(Long tenantId, Long mountId) {
+ aiMcpCacheStore.evictMcpMountCaches(tenantId, mountId);
+ aiConfigCacheStore.evictTenantConfigCaches(tenantId);
+ aiConversationCacheStore.evictTenantRuntimeCaches(tenantId);
}
}
--
Gitblit v1.9.1