From 63f8cc279de5671101336d8c338b5c7ec99977ad Mon Sep 17 00:00:00 2001 From: hhs <386998068@qq.com> Date: Sun, 14 Jun 2026 11:55:10 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20main.go=20=E4=BD=BF=E7=94=A8=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=80=BC=E6=9B=BF=E4=BB=A3=E7=A1=AC=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 版本号支持 -ldflags 构建时注入 - Session TTL/maxHistory 从配置读取 - 优雅关闭超时从配置读取 - AI 服务构造函数传入 HTTP Client 超时参数 --- backend/cmd/server/main.go | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/backend/cmd/server/main.go b/backend/cmd/server/main.go index 01a9b8e..829c415 100644 --- a/backend/cmd/server/main.go +++ b/backend/cmd/server/main.go @@ -22,6 +22,10 @@ import ( "github.com/hhs/camtalk/internal/ws" ) +// Version 通过构建时 -ldflags 注入,如: +// go build -ldflags "-X main.Version=v1.0.0" ./cmd/server +var Version string + var startTime = time.Now() func main() { @@ -43,7 +47,10 @@ func main() { // 初始化 Session Manager(MVP 默认内存实现) var sessionMgr session.Manager // TODO: 当 Redis 配置非空时切换为 RedisManager - sessionMgr = session.NewMemoryManager(30*time.Minute, 20) + sessionMgr = session.NewMemoryManager( + time.Duration(cfg.Session.TTL)*time.Minute, + cfg.Session.MaxHistory, + ) defer sessionMgr.(*session.MemoryManager).Stop() // 初始化 AI 服务 @@ -60,27 +67,27 @@ func main() { var sttService stt.Service switch strings.ToLower(cfg.AI.STT.Provider) { case "mimo", "xiaomi": - sttService = stt.NewMiMoService(cfg.AI.STT.APIKey, cfg.AI.STT.Model, cfg.AI.STT.Endpoint, logger.Log) + sttService = stt.NewMiMoService(cfg.AI.STT.APIKey, cfg.AI.STT.Model, cfg.AI.STT.Endpoint, cfg.AI.STT.Timeout, logger.Log) logger.Log.Infow("STT service initialized", "provider", "mimo", "model", cfg.AI.STT.Model, "endpoint", cfg.AI.STT.Endpoint) default: - sttService = stt.NewDeepgramService(cfg.AI.STT.APIKey, cfg.AI.STT.Model, cfg.AI.STT.Endpoint, logger.Log) + sttService = stt.NewDeepgramService(cfg.AI.STT.APIKey, cfg.AI.STT.Model, cfg.AI.STT.Endpoint, cfg.AI.STT.Timeout, logger.Log) logger.Log.Infow("STT service initialized", "provider", "deepgram", "model", cfg.AI.STT.Model) } - llmService := llm.NewOpenAIService(cfg.AI.LLM.APIKey, cfg.AI.LLM.Model, cfg.AI.LLM.Endpoint, cfg.AI.LLM.Timeout, logger.Log) + llmService := llm.NewOpenAIService(cfg.AI.LLM.APIKey, cfg.AI.LLM.Model, cfg.AI.LLM.Endpoint, cfg.AI.LLM.Timeout, cfg.AI.LLM.HTTPClientTimeout, logger.Log) logger.Log.Infow("LLM service initialized", "provider", cfg.AI.LLM.Provider, "model", cfg.AI.LLM.Model, "endpoint", cfg.AI.LLM.Endpoint, "timeout", cfg.AI.LLM.Timeout) var ttsService tts.Service switch strings.ToLower(cfg.AI.TTS.Provider) { case "mimo", "xiaomi": - ttsService = tts.NewMiMoService(cfg.AI.TTS.APIKey, cfg.AI.TTS.Model, cfg.AI.TTS.Voice, cfg.AI.TTS.Endpoint, cfg.AI.TTS.Timeout, logger.Log) + ttsService = tts.NewMiMoService(cfg.AI.TTS.APIKey, cfg.AI.TTS.Model, cfg.AI.TTS.Voice, cfg.AI.TTS.Endpoint, cfg.AI.TTS.Timeout, cfg.AI.TTS.HTTPClientTimeout, logger.Log) logger.Log.Infow("TTS service initialized", "provider", "mimo", "model", cfg.AI.TTS.Model, "voice", cfg.AI.TTS.Voice, "endpoint", cfg.AI.TTS.Endpoint) default: - ttsService = tts.NewOpenAIService(cfg.AI.TTS.APIKey, cfg.AI.TTS.Model, cfg.AI.TTS.Voice, cfg.AI.TTS.Endpoint, cfg.AI.TTS.Speed, cfg.AI.TTS.Timeout, logger.Log) + ttsService = tts.NewOpenAIService(cfg.AI.TTS.APIKey, cfg.AI.TTS.Model, cfg.AI.TTS.Voice, cfg.AI.TTS.Endpoint, cfg.AI.TTS.Speed, cfg.AI.TTS.Timeout, cfg.AI.TTS.HTTPClientTimeout, logger.Log) logger.Log.Infow("TTS service initialized", "provider", "openai", "model", cfg.AI.TTS.Model, "voice", cfg.AI.TTS.Voice, "speed", cfg.AI.TTS.Speed) } // 初始化 Orchestrator - orch := orchestrator.New(sttService, llmService, ttsService, sessionMgr, cfg.AI.LLM.Model, cfg.AI.TTS.Voice, cfg.AI.TTS.Speed) + orch := orchestrator.New(sttService, llmService, ttsService, sessionMgr, cfg) // Gin 模式 if cfg.App.Env == "prod" { @@ -93,7 +100,7 @@ func main() { // REST API apiGroup := r.Group("/api") { - apiGroup.GET("/health", healthHandler(sessionMgr)) + apiGroup.GET("/health", healthHandler(sessionMgr, cfg)) } // Session REST 端点 @@ -101,7 +108,7 @@ func main() { sessionHandler.RegisterRoutes(apiGroup) // WebSocket - r.GET("/ws", ws.ServeWS(sessionMgr, orch)) + r.GET("/ws", ws.ServeWS(sessionMgr, orch, cfg)) // HTTP Server srv := &http.Server{ @@ -125,7 +132,7 @@ func main() { <-ctx.Done() logger.Log.Info("shutting down...") - shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + shutdownCtx, cancel := context.WithTimeout(context.Background(), time.Duration(cfg.Server.ShutdownTimeout)*time.Second) defer cancel() if err := srv.Shutdown(shutdownCtx); err != nil { @@ -135,11 +142,15 @@ func main() { } // healthHandler 健康检查。 -func healthHandler(sessionMgr session.Manager) gin.HandlerFunc { +func healthHandler(sessionMgr session.Manager, cfg *config.Config) gin.HandlerFunc { return func(c *gin.Context) { + version := Version + if version == "" { + version = cfg.App.Version + } c.JSON(200, gin.H{ "status": "ok", - "version": "0.1.0", + "version": version, "uptime_seconds": int(time.Since(startTime).Seconds()), "active_sessions": sessionMgr.ActiveCount(), })