From 654f17d487f927248043555e756e9cb9cf41583e Mon Sep 17 00:00:00 2001 From: sp-lab Date: Tue, 30 Jun 2026 07:53:14 +0000 Subject: [PATCH] =?UTF-8?q?fix(mailsync):=20AI=20=EC=9A=94=EC=95=BD?= =?UTF-8?q?=EC=9D=B4=20NULL=20summary=20=ED=96=89=EC=9D=84=20=EB=AA=BB=20?= =?UTF-8?q?=EC=9E=A1=EB=8D=98=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기존 메일 569건은 summary 컬럼 추가 이전부터 있던 행이라 값이 NULL인데, 요약 대상 선택 쿼리가 summary='' 만 검색해서(SQL에서 NULL='' 는 거짓) 영원히 선택되지 않았다. COALESCE(summary,'')='' 로 NULL·빈문자열 모두 포함. 회당 상한 40→150으로 백로그 드레인 가속, 요약 실패는 silent skip 대신 로그로 남김. Co-Authored-By: Claude Opus 4.8 (1M context) --- internal/httpapi/mail_sync.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/httpapi/mail_sync.go b/internal/httpapi/mail_sync.go index e36ba10..9398b43 100644 --- a/internal/httpapi/mail_sync.go +++ b/internal/httpapi/mail_sync.go @@ -65,12 +65,19 @@ func syncProjectMail(ctx context.Context, db *gorm.DB, mailer *mailsync.Service, // AI 자동 요약: 아직 요약이 없는 메일에만 생성(긁어올 때마다 신규분에 채움). 비용·시간 // 폭주 방지로 회당 상한. + // 미생성 판정은 COALESCE(summary,'')='' — summary 컬럼 추가 이전에 저장된 행은 값이 + // NULL이라 `summary = ''`로는 영원히 안 잡혔다(SQL에서 NULL = '' 는 거짓). NULL·빈문자열 + // 둘 다 포함해야 기존 백로그도 채워진다. if cl := ai.New(aiKey); cl.Enabled() { var need []models.ProjectMailMsg - db.Where("project_id = ? AND summary = '' AND snippet <> ''", projectID).Limit(40).Find(&need) + db.Where("project_id = ? AND COALESCE(summary, '') = '' AND snippet <> ''", projectID).Limit(150).Find(&need) for _, row := range need { sum, err := cl.Summarize(ctx, row.Subject+"\n"+row.Snippet) - if err == nil && sum != "" { + if err != nil { + log.Printf("mailsync: AI 요약 실패 (project=%s msg=%s): %v", projectID, row.ID, err) + continue + } + if sum != "" { db.Model(&models.ProjectMailMsg{}).Where("id = ?", row.ID).Update("summary", sum) } }