bf6813e71d
生产网关在 /api 前丢掉 Upgrade 头,wss://…/chat/{userId} 到不了后端,
端上一直卡在「正在建立 WebSocket 连接…」。
- 新增 ApiChatWebSocketServer(/api/chat/{userId}),与老端点共用会话表;
会话表改存 Session 而不是端点实例,两条路径都能收到推送
- 登记会话时关闭空闲超时(Tomcat 默认 20s,AI 首字慢时会被掐断),
并补 @OnMessage 丢弃心跳(缺了它容器会因不支持的文本帧直接断连)
- send() 找不到 WS 会话时改投 ChatStreamRegistry,把帧送到 HTTP SSE 连接,
推送侧仍只有 sendMessage 一个入口,三千多次调用点不用改
- prod 放开 com.gxwebsoft.ai.config 到 INFO:只保留连接/断开,推送路径仍静默
- 补 ChatStreamRegistryTest / WebSocketEndpointPathTest / AiControllerSseFrameTest
顺带补上 31eb75c 漏加的 ChatStreamRegistry.java:AiController 已经 import 它,
缺文件时 HEAD 编译不过。
50 lines
1.8 KiB
Java
50 lines
1.8 KiB
Java
package com.gxwebsoft.ai.controller;
|
|
|
|
import com.gxwebsoft.common.core.web.ApiResult;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Map;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
|
/**
|
|
* SSE 末帧格式的回归测试。
|
|
*
|
|
* <p>出图这类「业务方法自己不推帧、只返回一个结果」的链路,结果靠末帧下发;
|
|
* 端上按 {@code type === 'final'} 识别。字段名一旦改了而端上没改,
|
|
* 表现为「流正常结束但页面一直转圈」,不容易在联调时发现,所以钉死格式。
|
|
*/
|
|
public class AiControllerSseFrameTest {
|
|
|
|
@Test
|
|
public void finalFrameMarksTypeAndKeepsResult() {
|
|
Map<String, Object> data = new LinkedHashMap<>();
|
|
data.put("photo_files", "[\"https://example.com/a.jpeg\"]");
|
|
|
|
String json = AiController.finalFrameJson(new ApiResult<>(0, "ok", data));
|
|
|
|
assertTrue(json.contains("\"type\":\"final\""), "末帧必须带 type=final,端上靠它区分业务帧");
|
|
assertTrue(json.contains("\"result\":{"), "业务返回值要原样放在 result 里");
|
|
assertTrue(json.contains("photo_files"), "返回体里的字段不能丢");
|
|
assertEquals(1, countOccurrences(json, "\"type\":"), "末帧只能有一个 type 字段");
|
|
}
|
|
|
|
@Test
|
|
public void finalFrameKeepsStringResult() {
|
|
String json = AiController.finalFrameJson("plain-text");
|
|
assertTrue(json.contains("\"result\":\"plain-text\""));
|
|
}
|
|
|
|
private static int countOccurrences(String text, String needle) {
|
|
int count = 0;
|
|
int index = text.indexOf(needle);
|
|
while (index != -1) {
|
|
count++;
|
|
index = text.indexOf(needle, index + needle.length());
|
|
}
|
|
return count;
|
|
}
|
|
}
|