diff --git a/troubleshooting/250825_gmail_token_null_daily_briefing_fix.md b/troubleshooting/250825_gmail_token_null_daily_briefing_fix.md index afe408f..6176614 100644 --- a/troubleshooting/250825_gmail_token_null_daily_briefing_fix.md +++ b/troubleshooting/250825_gmail_token_null_daily_briefing_fix.md @@ -1,9 +1,11 @@ -# Gmail 토큰 NULL로 인한 일일 브리핑 실패 해결 가이드 +# Gmail 토큰 NULL 및 대화 저장 실패 문제 해결 가이드 ## 작성일: 2025-08-25 ## 작성자: 서버 관리자 ## 상태: 해결 진행중 -## 영향: 매일 9시 브리핑 이메일 수집 실패 (사용자 3명) +## 영향: +- 매일 9시 브리핑 이메일 수집 실패 (사용자 3명) +- PostgreSQL 대화 저장 실패 (State Service DB 설정 오류) --- @@ -78,9 +80,7 @@ sequenceDiagram ## 3. 해결 방안 -### 3.1 단기 해결책 (즉시 적용) - -#### 방법 1: 관리자 대신 인증 (추천) +### 3.1 해결책 - 관리자 대신 인증 ```bash # 1. 테스트 계정으로 OAuth 인증 URL 생성 curl -X GET "http://localhost:9000/api/gmail/auth?user_id=1e16e9d5-59f3-54da-a661-8abeabff4230" @@ -99,59 +99,9 @@ curl -X POST http://192.168.219.52:8001/api/cron/daily-summary \ -H "Authorization: Bearer cron-secret-2024" ``` -#### 방법 2: 임시 토큰 주입 (비추천, 테스트용) -```sql --- 주의: 실제 유효한 토큰이 필요함 -UPDATE gmail_tokens -SET token_data = '{ - "access_token": "실제_액세스_토큰", - "refresh_token": "실제_리프레시_토큰", - "token_type": "Bearer", - "expires_in": 3599 -}'::jsonb, -expiry = NOW() + INTERVAL '1 hour' -WHERE user_id = '1e16e9d5-59f3-54da-a661-8abeabff4230'; -``` +### 3.2 해결책 - skill-email 토큰 자동 갱신 -### 3.2 중기 해결책 (사용자 재인증 유도) - -#### 프론트엔드에 알림 추가 -```javascript -// 로그인 시 Gmail 토큰 체크 -useEffect(() => { - checkGmailToken().then(hasToken => { - if (!hasToken) { - showNotification({ - title: "Gmail 재인증 필요", - message: "일일 브리핑을 위해 Gmail을 다시 연결해주세요", - action: "연결하기", - onClick: () => window.location.href = '/settings/gmail' - }); - } - }); -}, []); -``` - -#### Slack 메시지로 재인증 안내 -```python -# rb8001의 dm_skill.py에 추가 -async def notify_reauth_needed(user_slack_id: str): - await slack_client.chat_postMessage( - channel=user_slack_id, - text="🔔 Gmail 재인증이 필요합니다", - blocks=[{ - "type": "section", - "text": { - "type": "mrkdwn", - "text": "일일 브리핑을 위해 Gmail을 다시 연결해주세요:\nhttps://ro-being.com/settings/gmail" - } - }] - ) -``` - -### 3.3 장기 해결책 (자동 복구) - -#### 토큰 자동 갱신 구현 +#### auth-server의 기존 갱신 API 활용 ```python # skill-email 서비스에 추가 async def auto_refresh_token(user_id: str): @@ -188,12 +138,6 @@ psql -h localhost -U robeings -d main_db -c \ FROM users u LEFT JOIN gmail_tokens gt ON u.id = gt.user_id WHERE u.username IN ('happybell80', '0914eagle', 'cdctfm');" - -# 2. 크론잡 확인 -docker exec robeing-gateway crontab -l | grep daily - -# 3. 최근 실패 로그 확인 -ssh admin@192.168.219.52 "docker logs rb8001 --tail 100 | grep -E 'daily-summary|gmail|500'" 2>/dev/null || echo "직접 확인 필요" ``` ### Step 2: 테스트 계정 인증 (15분) @@ -234,24 +178,6 @@ curl -s "http://localhost:9000/api/gmail/auth?user_id=b6ea2ee0-a15a-5cf4-93a9-a9 curl -s "http://localhost:9000/api/gmail/auth?user_id=69ae4ea9-a15f-5110-9f5d-6568e380fcfb" | jq -r '.auth_url' ``` -### Step 5: 모니터링 설정 (10분) -```bash -# 매일 8시 50분 토큰 상태 체크 크론 추가 -cat << 'EOF' > /tmp/check_gmail_tokens.sh -#!/bin/bash -PGPASSWORD=robeings psql -h localhost -U robeings -d main_db -c \ - "SELECT username, token_data IS NOT NULL as has_token - FROM users u - JOIN gmail_tokens gt ON u.id = gt.user_id;" | \ -mail -s "Gmail Token Status" admin@ro-being.com -EOF - -chmod +x /tmp/check_gmail_tokens.sh - -# 크론잡 등록 (선택사항) -echo "50 8 * * * /tmp/check_gmail_tokens.sh" | crontab -l | crontab - -``` - --- ## 5. 검증 체크리스트 @@ -259,55 +185,68 @@ echo "50 8 * * * /tmp/check_gmail_tokens.sh" | crontab -l | crontab - - [ ] 모든 사용자의 token_data NOT NULL 확인 - [ ] 수동 브리핑 실행 시 이메일 포함 확인 - [ ] Slack DM으로 완전한 브리핑 수신 확인 -- [ ] 내일 9시 자동 실행 모니터링 예약 --- -## 6. 관련 파일 및 참고 문서 - -### 핵심 파일 -- **auth-server**: `/home/admin/auth-server/app/providers/gmail_passport.py` -- **게이트웨이 크론**: `/home/admin/robeing-gateway/app/crontab.py` -- **rb8001 브리핑**: `rb8001/app/skills/dm_skill.py:384` (51124 서버) +## 6. 관련 파일 +- **auth-server**: `/home/admin/auth-server/app/api/gmail_refresh.py` - **skill-email**: `skill-email/main.py` (51124 서버) - -### 참고 문서 -- [일일 브리핑 시퀀스 다이어그램](/home/admin/DOCS/300_architecture/sequences/daily_briefing_sequences.md) -- [Gmail 토큰 자동 갱신](/home/admin/DOCS/troubleshooting/250821_gmail_token_auto_refresh.md) -- [rb8001 크론 실패 분석](/home/admin/DOCS/troubleshooting/250824_rb8001_daily_summary_cron_failure.md) +- **State Service**: `/home/heejae/robeing-state-service/` (51124 서버) --- -## 7. 주의사항 +## 7. 대화 저장 문제 (추가 발견) -### ⚠️ 보안 관련 -- 실제 토큰을 로그에 출력하지 말 것 -- refresh_token은 절대 노출하지 말 것 -- 테스트 후 불필요한 토큰은 삭제 +### 7.1 문제 상황 +- **증상**: Slack DM 대화가 PostgreSQL에 저장 안됨 +- **ChromaDB**: ✅ 정상 저장 +- **PostgreSQL**: ❌ 저장 실패 (conversation_logs 테이블 0 rows) -### ⚠️ 운영 관련 -- 프로덕션 사용자의 토큰 직접 수정 지양 -- 사용자에게 재인증 안내 우선 -- 크론 실행 시간(9시) 피해서 테스트 +### 7.2 대화 저장 플로우 +```mermaid +sequenceDiagram + participant User as Slack User + participant RB as rb8001
(51124:8001) + participant State as State Service
(51124:8507) + participant Chroma as ChromaDB
(51124:8000) + participant PG as PostgreSQL
(51123:5432) + + User->>RB: "하이" + RB->>RB: 메시지 처리 + RB-->>User: "안녕하세요, 김종태님!" + + RB->>Chroma: store_memory() + Chroma-->>RB: ✅ 저장 성공
ID: 2a776b26... + + RB->>State: POST /api/logs/rb8001/conversation + State->>PG: INSERT INTO conversation_logs
❌ DB 연결 실패 + Note over State,PG: 잘못된 DB 설정:
localhost:5433/auth_db + State-->>RB: 500 Internal Server Error + + Note over RB: 에러 로깅만,
서비스 계속 동작 +``` + +### 7.3 근본 원인 +**State Service 환경변수 오류**: +```bash +# 현재 (잘못된 설정) +DATABASE_URL=postgresql://robeings:robeings@localhost:5433/auth_db + +# 올바른 설정 +DATABASE_URL=postgresql://robeings:robeings@192.168.219.45:5432/main_db +``` + +### 7.4 해결 방법 +```bash +# State Service 환경변수 수정 (51124 서버) +cd /home/heejae/robeing-state-service +vim .env # DATABASE_URL 수정 +docker compose down && docker compose up -d --build +``` --- -## 8. 문제 재발 방지 +## 예상 소요 시간: 1시간 30분 -### 단기 조치 -1. 토큰 만료 알림 시스템 구축 -2. 관리자 대시보드에 토큰 상태 표시 - -### 장기 조치 -1. refresh_token 자동 갱신 로직 구현 -2. 토큰 만료 7일 전 사용자 알림 -3. 프론트엔드 Gmail 연결 상태 표시 개선 - ---- - -## 예상 소요 시간: 1시간 - -- Step 1-2: 20분 (기본 인증) -- Step 3: 10분 (테스트) -- Step 4: 20분 (추가 사용자) -- Step 5: 10분 (모니터링) \ No newline at end of file +- Gmail 토큰 문제: 1시간 +- State Service DB 설정: 30분 \ No newline at end of file