Merge branch 'main' of https://git.ro-being.com/ivada_Ro-being/DOCS
This commit is contained in:
commit
f4a9320828
222
troubleshooting/250826_happybell80_rb8001_이중저장구현.md
Normal file
222
troubleshooting/250826_happybell80_rb8001_이중저장구현.md
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
# rb8001 대화 이중 저장 시스템 구현
|
||||||
|
|
||||||
|
## 작성일: 2025-08-26
|
||||||
|
## 작성자: happybell80
|
||||||
|
## 관련 서비스: rb8001, PostgreSQL, ChromaDB
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 문제 상황
|
||||||
|
|
||||||
|
### 기존 문제점
|
||||||
|
1. **State Service 의존성**
|
||||||
|
- rb8001이 State Service (포트 8507) API 호출
|
||||||
|
- State Service가 auth_db로 잘못 연결되어 500 에러 발생
|
||||||
|
- 대화가 ChromaDB에만 저장되고 PostgreSQL 저장 실패
|
||||||
|
|
||||||
|
2. **데이터 불일치**
|
||||||
|
- ChromaDB: 대화 저장 성공
|
||||||
|
- PostgreSQL: State Service 오류로 저장 실패
|
||||||
|
- 단일 실패 지점(SPOF) 존재
|
||||||
|
|
||||||
|
3. **네트워크 오버헤드**
|
||||||
|
- 불필요한 HTTP API 호출
|
||||||
|
- State Service 중간 단계로 인한 지연
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 조사 과정
|
||||||
|
|
||||||
|
### 1. 로컬 코드 분석
|
||||||
|
```bash
|
||||||
|
# rb8001 대화 저장 로직 확인
|
||||||
|
grep -r "save_conversation\|store_memory" rb8001/
|
||||||
|
|
||||||
|
# 결과:
|
||||||
|
# - router.py:309: _save_conversation() 메서드
|
||||||
|
# - ChromaDB 직접 저장 + State Service API 호출
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 서버 상태 확인 (51124)
|
||||||
|
```bash
|
||||||
|
# PostgreSQL 연결 테스트
|
||||||
|
PGPASSWORD=robeings psql -h 192.168.219.45 -U robeings -d main_db -c "\dt"
|
||||||
|
|
||||||
|
# 결과:
|
||||||
|
# - conversation_logs 테이블 존재 ✅
|
||||||
|
# - robeing_stats 테이블 존재 ✅
|
||||||
|
# - 직접 연결 가능
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. SSH 터널 문제 발견
|
||||||
|
```bash
|
||||||
|
# 기존 터널 (잘못된 설정)
|
||||||
|
localhost:5433 → 124.55.18.179:5432/auth_db (존재하지 않음)
|
||||||
|
|
||||||
|
# 수정된 터널
|
||||||
|
localhost:5433 → 192.168.219.45:5432/main_db ✅
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 해결 방안
|
||||||
|
|
||||||
|
### 1. DATABASE_URL 수정
|
||||||
|
```diff
|
||||||
|
# rb8001/.env
|
||||||
|
- DATABASE_URL=postgresql://robeings:robeing2025!@localhost/rb8001_db
|
||||||
|
+ DATABASE_URL=postgresql://robeings:robeings@192.168.219.45:5432/main_db
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 직접 DB 저장 구현
|
||||||
|
```python
|
||||||
|
# rb8001/app/router/router.py:309
|
||||||
|
async def _save_conversation(self, message: str, response: str, user_id: str,
|
||||||
|
channel: str, intent: str = None, confidence: float = None):
|
||||||
|
"""대화를 PostgreSQL과 ChromaDB에 직접 저장"""
|
||||||
|
chroma_saved = False
|
||||||
|
postgres_saved = False
|
||||||
|
|
||||||
|
# 1. ChromaDB에 저장 시도
|
||||||
|
try:
|
||||||
|
await self.memory_manager.store_memory(...)
|
||||||
|
chroma_saved = True
|
||||||
|
logger.info(f"ChromaDB: Conversation saved for user {user_id}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"ChromaDB save failed: {e}")
|
||||||
|
|
||||||
|
# 2. PostgreSQL에 직접 저장 시도
|
||||||
|
try:
|
||||||
|
from app.state.database import SessionLocal
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
conversation_log = ConversationLog(
|
||||||
|
robeing_id=settings.ROBEING_ID,
|
||||||
|
user_id=user_id,
|
||||||
|
channel_id=channel,
|
||||||
|
message=message,
|
||||||
|
response=response,
|
||||||
|
intent=intent,
|
||||||
|
confidence=confidence
|
||||||
|
)
|
||||||
|
db.add(conversation_log)
|
||||||
|
db.commit()
|
||||||
|
postgres_saved = True
|
||||||
|
logger.info(f"PostgreSQL: Conversation saved for user {user_id}")
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"PostgreSQL save failed: {e}")
|
||||||
|
|
||||||
|
# 최소 하나는 성공해야 함
|
||||||
|
if not chroma_saved and not postgres_saved:
|
||||||
|
logger.error("Failed to save conversation to both storages")
|
||||||
|
elif chroma_saved and postgres_saved:
|
||||||
|
logger.info(f"Conversation saved to both storages for user {user_id}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. State Service 의존성 제거
|
||||||
|
- HTTP API 호출 코드 제거
|
||||||
|
- 직접 SQLAlchemy 사용
|
||||||
|
- 트랜잭션 처리 추가
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 구현 결과
|
||||||
|
|
||||||
|
### 장점
|
||||||
|
1. **안정성 향상**
|
||||||
|
- 한쪽 저장소 실패해도 다른 쪽 저장 보장
|
||||||
|
- 트랜잭션 단위 에러 처리
|
||||||
|
|
||||||
|
2. **성능 개선**
|
||||||
|
- State Service API 호출 제거
|
||||||
|
- 네트워크 지연 감소
|
||||||
|
- 직접 DB 연결로 빠른 저장
|
||||||
|
|
||||||
|
3. **관리 단순화**
|
||||||
|
- State Service 별도 관리 불필요
|
||||||
|
- 단일 서비스 내 모든 로직 포함
|
||||||
|
|
||||||
|
### 데이터 흐름
|
||||||
|
```mermaid
|
||||||
|
graph LR
|
||||||
|
A[Slack 메시지] --> B[rb8001]
|
||||||
|
B --> C{저장 로직}
|
||||||
|
C --> D[ChromaDB<br/>벡터 저장]
|
||||||
|
C --> E[PostgreSQL<br/>구조화 저장]
|
||||||
|
D --> F[저장 결과 로깅]
|
||||||
|
E --> F
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 모니터링
|
||||||
|
|
||||||
|
### 로그 확인
|
||||||
|
```bash
|
||||||
|
# 51124 서버에서
|
||||||
|
docker logs rb8001 --tail 100 | grep -E "ChromaDB|PostgreSQL|saved"
|
||||||
|
|
||||||
|
# 성공 로그 예시:
|
||||||
|
# ChromaDB: Conversation saved for user U092HLS6BKL
|
||||||
|
# PostgreSQL: Conversation saved for user U092HLS6BKL
|
||||||
|
# Conversation saved to both storages for user U092HLS6BKL
|
||||||
|
```
|
||||||
|
|
||||||
|
### DB 확인
|
||||||
|
```sql
|
||||||
|
-- PostgreSQL 저장 확인
|
||||||
|
SELECT COUNT(*) FROM conversation_logs
|
||||||
|
WHERE robeing_id = 'rb8001'
|
||||||
|
AND timestamp > NOW() - INTERVAL '1 hour';
|
||||||
|
|
||||||
|
-- 최근 대화 확인
|
||||||
|
SELECT user_id, message, response, timestamp
|
||||||
|
FROM conversation_logs
|
||||||
|
WHERE robeing_id = 'rb8001'
|
||||||
|
ORDER BY timestamp DESC
|
||||||
|
LIMIT 5;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 교훈
|
||||||
|
|
||||||
|
### 1. 아키텍처 단순화
|
||||||
|
- **문제**: 불필요한 중간 서비스로 인한 복잡도
|
||||||
|
- **해결**: 직접 연결로 단순화
|
||||||
|
- **교훈**: KISS 원칙 - Keep It Simple, Stupid
|
||||||
|
|
||||||
|
### 2. 이중 저장의 중요성
|
||||||
|
- **ChromaDB**: 벡터 검색용 (의미 기반 검색)
|
||||||
|
- **PostgreSQL**: 구조화 데이터 (통계, 분석)
|
||||||
|
- **교훈**: 각 저장소의 장점을 활용한 하이브리드 접근
|
||||||
|
|
||||||
|
### 3. 에러 처리 전략
|
||||||
|
- **부분 실패 허용**: 한쪽만 성공해도 서비스 계속
|
||||||
|
- **명확한 로깅**: 어느 저장소가 실패했는지 구분
|
||||||
|
- **교훈**: Graceful degradation 구현
|
||||||
|
|
||||||
|
### 4. SSH 터널 관리
|
||||||
|
- **문제**: 잘못된 터널 설정으로 auth_db 연결 시도
|
||||||
|
- **해결**: main_db로 터널 재설정
|
||||||
|
- **교훈**: 인프라 설정 문서화 필수
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 관련 파일
|
||||||
|
- `/home/happybell/projects/ivada/rb8001/.env` - DATABASE_URL 설정
|
||||||
|
- `/home/happybell/projects/ivada/rb8001/app/router/router.py` - 저장 로직
|
||||||
|
- `/home/happybell/projects/ivada/rb8001/app/state/database.py` - DB 모델
|
||||||
|
- `/home/happybell/projects/ivada/rb8001/app/memory/manager.py` - ChromaDB 관리
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 참고 문서
|
||||||
|
- [일일 브리핑 시퀀스](/home/happybell/projects/ivada/DOCS/300_architecture/sequences/daily_briefing_sequences.md)
|
||||||
|
- [로빙 상태 표시 문제](/home/happybell/projects/ivada/DOCS/troubleshooting/250825_robeing_stats_display_issue.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**문서 끝**
|
||||||
Loading…
x
Reference in New Issue
Block a user