package controllers import ( "intent-system/pkg/dal/core" "net/http" "time" "github.com/civet148/log" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" ) var upgrader1 = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { // 开发阶段允许所有来源,生产环境你可以限制 return true }, } func (m *Controller) DeployStatusWS(c *gin.Context) { appID := c.Param("appID") username := c.Param("user") conn, err := upgrader1.Upgrade(c.Writer, c.Request, nil) if err != nil { log.Warnf("WebSocket 升级失败: %v", err) return } defer conn.Close() // 设置超时时间 conn.SetReadDeadline(time.Now().Add(60 * time.Second)) // 接收到 pong 帧,刷新 ReadDeadline conn.SetPongHandler(func(string) error { conn.SetReadDeadline(time.Now().Add(60 * time.Second)) return nil }) // 启动 ping 心跳(后台 goroutine 定时发 ping) go func() { ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() for range ticker.C { // 发送 ping 帧,保持连接活跃 if err := conn.WriteControl(websocket.PingMessage, []byte("ping"), time.Now().Add(10*time.Second)); err != nil { log.Warnf("发送 ping 失败: %v", err) return } log.Debugf("➡️ 已发送 ping 帧到客户端") } }() // 获取部署任务并 attach task := core.GlobalTaskManager.Get(appID) if task == nil { conn.WriteMessage(websocket.TextMessage, []byte("任务未启动或已结束")) return } task.Attach(conn, username) defer task.Detach(conn) // 保持连接监听(用于捕获客户端断开) for { if _, _, err := conn.ReadMessage(); err != nil { log.Infof("🔌 客户端断开(%s/%s): %v", username, appID, err) break } } }