Stats API 일원화
This commit is contained in:
parent
910d8f6afa
commit
bc7bea66d0
@ -14,7 +14,7 @@
|
|||||||
## 🟠 Major Projects (높은 중요도 + 어려운 구현) → 계획 수립 후 진행
|
## 🟠 Major Projects (높은 중요도 + 어려운 구현) → 계획 수립 후 진행
|
||||||
1. **skill-rag-file 핵심 엔드포인트 구현** - /upload, /search, /healthz(포트 8508), Chroma 연동 (3주) [→250915](../troubleshooting/250915_skill-rag-file_초기_구축.md) --> ( **solved - 2025-09-20 확인, 모든 엔드포인트 구현 완료 및 서비스 운영 중** )
|
1. **skill-rag-file 핵심 엔드포인트 구현** - /upload, /search, /healthz(포트 8508), Chroma 연동 (3주) [→250915](../troubleshooting/250915_skill-rag-file_초기_구축.md) --> ( **solved - 2025-09-20 확인, 모든 엔드포인트 구현 완료 및 서비스 운영 중** )
|
||||||
2. **News 시스템 DB 영속화 단계** - rb_news 등 저장 파트 구현(Phase 3) (2주) [→250906](250906_news_system_integration.md) --> ( **solved - 2025-09-20 rb_news 테이블 생성 및 저장 기능 구현 완료** )
|
2. **News 시스템 DB 영속화 단계** - rb_news 등 저장 파트 구현(Phase 3) (2주) [→250906](250906_news_system_integration.md) --> ( **solved - 2025-09-20 rb_news 테이블 생성 및 저장 기능 구현 완료** )
|
||||||
3. **Stats API 일원화** - 경로(/api/stats vs /stats)·스키마(robeing_id/robeing_container_id, ethics/stat_points) 통일 (1주) [→250915](../troubleshooting/250915_happybell80_rb8001_stats_api_중복_제거.md)
|
3. **Stats API 일원화** - 경로(/api/stats vs /stats)·스키마(robeing_id/robeing_container_id, ethics/stat_points) 통일 (1주) [→250915](../troubleshooting/250915_happybell80_rb8001_stats_api_중복_제거.md) --> ( **solved - 2025-09-20 robeing-monitor로 일원화 완료** [→구현](../troubleshooting/250920_stats_api_unification_complete.md) )
|
||||||
4. **사용자 식별 통합 고도화** - UUID 1차 식별자 일원화(슬랙·지메일 매핑 테이블) (2주) [→250831](250831_unified_id_system_implementation_roadmap.md), [→250827](../troubleshooting/250827_claude_conversation_log_user_mapping.md)
|
4. **사용자 식별 통합 고도화** - UUID 1차 식별자 일원화(슬랙·지메일 매핑 테이블) (2주) [→250831](250831_unified_id_system_implementation_roadmap.md), [→250827](../troubleshooting/250827_claude_conversation_log_user_mapping.md)
|
||||||
5. **하드코딩 URL 제거** - 15개+ 서비스 전체 환경변수화 (3-4주) [→250915](../troubleshooting/250915_hardcoded_url_removal.md)
|
5. **하드코딩 URL 제거** - 15개+ 서비스 전체 환경변수화 (3-4주) [→250915](../troubleshooting/250915_hardcoded_url_removal.md)
|
||||||
6. **Gateway 스케일링** - 재시도/백오프/헬스체크 (1주) [→250811](../troubleshooting/250811_happybell80_Gateway필드변환문제.md)
|
6. **Gateway 스케일링** - 재시도/백오프/헬스체크 (1주) [→250811](../troubleshooting/250811_happybell80_Gateway필드변환문제.md)
|
||||||
|
|||||||
168
troubleshooting/250920_stats_api_unification_complete.md
Normal file
168
troubleshooting/250920_stats_api_unification_complete.md
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
# Stats API 일원화 구현 완료
|
||||||
|
|
||||||
|
## 개요
|
||||||
|
- **일시**: 2025-09-20
|
||||||
|
- **작업자**: Claude Code
|
||||||
|
- **목표**: rb8001과 robeing-monitor의 중복된 Stats API를 robeing-monitor로 일원화
|
||||||
|
- **결과**: ✅ 성공
|
||||||
|
|
||||||
|
## 문제 상황
|
||||||
|
|
||||||
|
### 1. 중복 구현
|
||||||
|
- **rb8001**: 자체 stats 관리 (`/stats`, `/api/stats/{robeing_id}`)
|
||||||
|
- **robeing-monitor**: 별도 stats 관리 (`/api/stats/{robeing_id}`)
|
||||||
|
- 두 서비스가 동일한 DB 테이블(`robeing`)을 다른 스키마로 접근
|
||||||
|
|
||||||
|
### 2. 스키마 불일치
|
||||||
|
- **rb8001 ORM 모델**: `robeing_id` 필드 (실제 DB에 없음)
|
||||||
|
- **robeing-monitor ORM 모델**: `robeing_container_id` 필드 (실제 DB와 일치)
|
||||||
|
- **실제 DB 테이블**: UUID primary key, `robeing_container_id` 사용
|
||||||
|
|
||||||
|
### 3. 데이터 불일치 위험
|
||||||
|
- 두 서비스가 독립적으로 stats 관리
|
||||||
|
- 동일 테이블에 대한 경합 조건 발생 가능
|
||||||
|
- 데이터 일관성 보장 불가
|
||||||
|
|
||||||
|
## 해결 방안
|
||||||
|
|
||||||
|
### 전략: robeing-monitor를 단일 소스로 통합
|
||||||
|
robeing-monitor가 이미 실제 DB 스키마와 일치하고, 여러 서비스에서 사용 가능하므로 Stats 관리의 단일 소스로 지정
|
||||||
|
|
||||||
|
## 구현 내용
|
||||||
|
|
||||||
|
### 1. rb8001 환경변수 설정
|
||||||
|
```bash
|
||||||
|
# /home/admin/ivada_project/rb8001/.env
|
||||||
|
STATE_SERVICE_URL=http://localhost:9024
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. rb8001 /stats 엔드포인트 수정
|
||||||
|
```python
|
||||||
|
# main.py
|
||||||
|
@app.get("/stats")
|
||||||
|
async def get_stats():
|
||||||
|
"""현재 로빙의 스탯 조회 - robeing-monitor에서 가져옴"""
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
response = await client.get(
|
||||||
|
f"{settings.STATE_SERVICE_URL}/api/stats/{settings.ROBEING_ID}",
|
||||||
|
timeout=5.0
|
||||||
|
)
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
return {
|
||||||
|
"robeing_id": settings.ROBEING_ID,
|
||||||
|
"stats": {
|
||||||
|
"memory": data.get("memory", 10),
|
||||||
|
"compute": data.get("compute", 10),
|
||||||
|
"react": data.get("react", 10),
|
||||||
|
"empathy": data.get("empathy", 10),
|
||||||
|
"leadership": data.get("leadership", 10)
|
||||||
|
},
|
||||||
|
"level": data.get("level", 1)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. rb8001 초기화 로직 수정
|
||||||
|
```python
|
||||||
|
# app/router/router.py
|
||||||
|
async def _load_stats_from_state(self):
|
||||||
|
"""State Service(robeing-monitor)에서 스탯 로드"""
|
||||||
|
try:
|
||||||
|
if not settings.STATE_SERVICE_URL:
|
||||||
|
logger.warning("STATE_SERVICE_URL not configured")
|
||||||
|
return
|
||||||
|
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
response = await client.get(
|
||||||
|
f"{settings.STATE_SERVICE_URL}/api/stats/{settings.ROBEING_ID}",
|
||||||
|
timeout=5.0
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
from app.brain.stats_manager import RobeingStats
|
||||||
|
self.stats = RobeingStats(
|
||||||
|
memory=data.get("memory", 10),
|
||||||
|
compute=data.get("compute", 10),
|
||||||
|
react=data.get("react", 10),
|
||||||
|
empathy=data.get("empathy", 10),
|
||||||
|
leadership=data.get("leadership", 10)
|
||||||
|
)
|
||||||
|
logger.info(f"Stats loaded from robeing-monitor: {self.stats}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. rb8001 중복 코드 제거
|
||||||
|
```python
|
||||||
|
# app/state/state_service.py
|
||||||
|
# stats 관련 엔드포인트 주석 처리
|
||||||
|
# @app.get("/api/stats/{robeing_id}")
|
||||||
|
# @app.put("/api/stats/{robeing_id}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. robeing-monitor PUT 엔드포인트 활성화
|
||||||
|
```python
|
||||||
|
# /home/admin/ivada_project/robeing-monitor/app/main.py
|
||||||
|
# State Service 엔드포인트 마운트 추가
|
||||||
|
app.mount("/api", state_service.app)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 테스트 결과
|
||||||
|
|
||||||
|
### 1. GET 테스트
|
||||||
|
```bash
|
||||||
|
# robeing-monitor 직접 조회
|
||||||
|
curl http://localhost:9024/api/stats/rb8001
|
||||||
|
# 결과: {"memory": 10, "compute": 10, "react": 10, ...}
|
||||||
|
|
||||||
|
# rb8001 프록시 조회
|
||||||
|
curl http://localhost:8001/stats
|
||||||
|
# 결과: {"robeing_id": "rb8001", "stats": {...}, "level": 3}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. PUT 테스트
|
||||||
|
```bash
|
||||||
|
# Stats 업데이트
|
||||||
|
curl -X PUT http://localhost:9024/api/stats/rb8001 \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"memory": 15, "compute": 12}'
|
||||||
|
|
||||||
|
# rb8001에서 확인
|
||||||
|
curl http://localhost:8001/stats
|
||||||
|
# 결과: 업데이트된 값 반영 확인
|
||||||
|
```
|
||||||
|
|
||||||
|
## 효과
|
||||||
|
|
||||||
|
### 1. 데이터 일관성
|
||||||
|
- 단일 소스(robeing-monitor)에서만 stats 관리
|
||||||
|
- 데이터 불일치 문제 해결
|
||||||
|
|
||||||
|
### 2. 유지보수성
|
||||||
|
- 중복 코드 제거
|
||||||
|
- 명확한 책임 분리
|
||||||
|
|
||||||
|
### 3. 확장성
|
||||||
|
- 다른 서비스도 robeing-monitor API 사용 가능
|
||||||
|
- 중앙 집중식 stats 관리
|
||||||
|
|
||||||
|
## 주의사항
|
||||||
|
|
||||||
|
1. **DB 스키마**: 실제 테이블은 `robeing_container_id` 사용 (not `robeing_id`)
|
||||||
|
2. **Primary Key**: UUID 타입 (not Integer)
|
||||||
|
3. **환경변수**: `STATE_SERVICE_URL` 필수 설정
|
||||||
|
4. **의존성**: robeing-monitor 서비스가 먼저 실행되어야 함
|
||||||
|
|
||||||
|
## 교훈
|
||||||
|
|
||||||
|
1. **DB 스키마 우선 확인**: ORM 모델 작성 전 실제 테이블 구조 확인 필수
|
||||||
|
2. **서비스 책임 명확화**: 동일 기능 중복 구현 방지
|
||||||
|
3. **API 경로 일관성**: GET과 PUT이 동일한 경로 패턴 사용하도록 설계
|
||||||
|
4. **통합 테스트 중요성**: 단순 조회뿐만 아니라 업데이트 기능도 테스트
|
||||||
|
|
||||||
|
## 관련 파일
|
||||||
|
- `/home/admin/ivada_project/rb8001/main.py`
|
||||||
|
- `/home/admin/ivada_project/rb8001/app/router/router.py`
|
||||||
|
- `/home/admin/ivada_project/rb8001/app/state/state_service.py`
|
||||||
|
- `/home/admin/ivada_project/robeing-monitor/app/main.py`
|
||||||
|
- `/home/admin/ivada_project/robeing-monitor/app/state/state_service.py`
|
||||||
Loading…
x
Reference in New Issue
Block a user