From 174eb7cf272b2d459dda28bdfd9c0511f37f3335 Mon Sep 17 00:00:00 2001 From: qhd <1766646056@qq.com> Date: Sat, 22 Aug 2026 09:58:12 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=B5=81=E5=BC=8F=E8=B0=83=E7=94=A8?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E6=97=B6=E5=86=99=E5=85=A5=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E4=BC=9A=E8=AF=9D=E9=94=99=E8=AF=AF=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service/model_session_service.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/service/model_session_service.go b/service/model_session_service.go index b0c5fff..5de63a6 100644 --- a/service/model_session_service.go +++ b/service/model_session_service.go @@ -160,11 +160,14 @@ LOOP: g.Log().Warningf(ctx, "模型流式请求异常,第 %d 次重试(等待 %v): code=%s err=%v", attempt+1, wait, retryCode, err) select { case <-ctx.Done(): + recordSessionError(context.WithoutCancel(ctx), id, startTime, "调用取消: "+ctx.Err().Error()) return nil, ctx.Err() case <-time.After(wait): } goto LOOP } + // 非重试错误/重试耗尽:请求失败即返回,需把失败信息写入模型会话记录,避免留半截无错误信息记录 + recordSessionError(ctx, id, startTime, err.Error()) return nil, err } @@ -226,6 +229,7 @@ LOOP: g.Log().Warningf(ctx, "模型流式调用异常,第 %d 次重试(等待 %v): code=%s msg=%s", attempt+1, wait, streamErrCode, streamErrMsg) select { case <-ctx.Done(): + recordSessionError(context.WithoutCancel(ctx), id, startTime, "调用取消: "+ctx.Err().Error()) return nil, ctx.Err() case <-time.After(wait): } @@ -283,6 +287,8 @@ func (s *modelSessionService) CreateSessionStream(ctx context.Context, w http.Re // 获取上游流式 reader 并设置 SSE 响应头 streamReader, err := ModelHttpStreamRequest(ctx, w, modelInfo.BaseURL, modelInfo.RequestHeadMapping, modelInfo.HttpMethod, newRequestParams) if err != nil { + // 请求建立前失败:把错误写入模型会话记录,避免留半截无错误信息记录 + recordSessionError(ctx, id, startTime, err.Error()) return nil, err } @@ -441,6 +447,19 @@ func (s *modelSessionService) CreateSessionStream(ctx context.Context, w http.Re return docMsg, nil } +// recordSessionError 请求建立前失败(上游不可达/非 2xx 且非重试/重试耗尽/调用取消)时, +// 把错误与耗时写入模型会话记录,避免流式调用留半截无错误信息记录。 +// 仅写 ErrorMsg/DurationSeconds(OmitEmpty 不会影响已落库字段);ctx 已取消时须传 WithoutCancel(ctx)。 +func recordSessionError(ctx context.Context, id int64, startTime time.Time, errMsg string) { + if _, updateErr := dao.ModelSession.Update(ctx, &dto.UpdateModelSessionReq{ + Id: id, + DurationSeconds: int64(time.Since(startTime).Seconds()), + ErrorMsg: errMsg, + }); updateErr != nil { + g.Log().Errorf(ctx, "更新模型会话错误信息失败: %v", updateErr) + } +} + // isRetryableErrorCode 判定上游返回的错误码是否可重试:限流(429/limit_requests/limit_tokens/rate_limit_exceeded)与 5xx(500-503)。 // ModelHttpNormalRequest 不返回 HTTP status,只能按响应体 error.code 字符串判定。 func isRetryableErrorCode(code string) bool {