fix(server): thread request ctx through session bootstrap, drop Background DB calls
- getOrCreateSession now takes ctx; GetSessionOwnerID/ RestoreSessionContext/CompilePromptGuidance run under context.WithTimeout(5s) instead of context.Background() - SyncRecentDialogue's rolling summary uses a 30s timeout context instead of Background, so client disconnect cancels the LLM call Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -176,7 +176,9 @@ func (s *Session) SyncRecentDialogue() {
|
||||
|
||||
// 若发生了截断且存在早期消息,同步计算或加载滚动摘要
|
||||
if truncated && len(early) > 0 && s.CtxMgr != nil {
|
||||
s.syncDialogueSummary(context.Background(), early)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
s.syncDialogueSummary(ctx, early)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ func (s *Server) handleGetProject(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
sess, err := s.getOrCreateSession(0, sessionID, "", "", "", "", "", "", "", "")
|
||||
sess, err := s.getOrCreateSession(r.Context(), 0, sessionID, "", "", "", "", "", "", "", "")
|
||||
if err != nil || sess == nil || sess.UserCtx == nil {
|
||||
writeSafeError(w, r, http.StatusNotFound, "session or project context not found")
|
||||
return
|
||||
@@ -170,6 +170,7 @@ func (s *Server) handleChat(w http.ResponseWriter, r *http.Request) {
|
||||
req.WorkDir = ""
|
||||
|
||||
sess, err := s.getOrCreateSession(
|
||||
r.Context(),
|
||||
user.ID,
|
||||
req.SessionID,
|
||||
req.ProjectName,
|
||||
|
||||
@@ -403,6 +403,7 @@ func (s *Server) cleanStaleSessionsLocked(ttl time.Duration) int {
|
||||
|
||||
// getOrCreateSession 获取或动态构建会话。callerUserID>0 时校验持久层归属,不匹配返回 ErrSessionOwnerMismatch。
|
||||
func (s *Server) getOrCreateSession(
|
||||
ctx context.Context,
|
||||
callerUserID int64,
|
||||
sessionID string,
|
||||
projectName string,
|
||||
@@ -420,7 +421,10 @@ func (s *Server) getOrCreateSession(
|
||||
|
||||
// 归属校验必须先于任何缓存命中/持久层灌入
|
||||
if callerUserID > 0 && s.ctxMgr != nil {
|
||||
if owner, err := s.ctxMgr.GetSessionOwnerID(context.Background(), sessionID); err == nil && owner > 0 && owner != callerUserID {
|
||||
dbCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
owner, err := s.ctxMgr.GetSessionOwnerID(dbCtx, sessionID)
|
||||
cancel()
|
||||
if err == nil && owner > 0 && owner != callerUserID {
|
||||
return nil, ctxmgr.ErrSessionOwnerMismatch
|
||||
}
|
||||
}
|
||||
@@ -455,7 +459,10 @@ func (s *Server) getOrCreateSession(
|
||||
// 尝试从持久层恢复会话上下文 (服务重启后跨进程保持 G3)
|
||||
var restored *ctxmgr.RestoredSessionContext
|
||||
if s.ctxMgr != nil {
|
||||
if r, err := s.ctxMgr.RestoreSessionContext(context.Background(), sessionID); err == nil && r != nil && len(r.Messages) > 0 {
|
||||
dbCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
r, err := s.ctxMgr.RestoreSessionContext(dbCtx, sessionID)
|
||||
cancel()
|
||||
if err == nil && r != nil && len(r.Messages) > 0 {
|
||||
restored = r
|
||||
}
|
||||
}
|
||||
@@ -563,7 +570,10 @@ func (s *Server) getOrCreateSession(
|
||||
}
|
||||
|
||||
if sess.UserID > 0 && sess.CtxMgr != nil {
|
||||
if guidance, err := sess.CtxMgr.CompilePromptGuidance(context.Background(), sess.UserID); err == nil && guidance != "" {
|
||||
dbCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
guidance, err := sess.CtxMgr.CompilePromptGuidance(dbCtx, sess.UserID)
|
||||
cancel()
|
||||
if err == nil && guidance != "" {
|
||||
_ = coordinator.ApplyContextUpdate(userCtx, coordinator.ContextUpdate{
|
||||
ExpectedVersion: userCtx.Version,
|
||||
SetPersonalizedGuidance: true,
|
||||
|
||||
@@ -174,6 +174,7 @@ func (s *Server) handleChatStream(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// 会话与项目绑定必须在 SSE headers/Flush 之前完成授权(与 tasks/run/stream 对齐)
|
||||
sess, err := s.getOrCreateSession(
|
||||
r.Context(),
|
||||
user.ID,
|
||||
req.SessionID,
|
||||
req.ProjectName,
|
||||
|
||||
Reference in New Issue
Block a user