03_rag: - companyx_grounding_pipeline.md: 코드 SSOT 섹션 추가, 진입 조건 3단계(IC→마커 폴백) 정확히 기술, 환경변수 참조로 IP 하드코딩 제거 - companyx_incremental_indexing_workflow.md: frontmatter 표준 적용 (type, last_updated) - rag_upload_indexing_pipeline.md: 코드 SSOT·재인덱싱·업로드 경로별 진입점 테이블 추가, 환경변수 참조 04_scheduler: - scheduled_daily_briefing.md: n8n cron 전제 제거, APScheduler DB 기반 + LangGraph 워크플로우 기준 재작성 - scheduled_healthcheck_alert.md: n8n cron 전제 제거, /health 엔드포인트 + SKILL.md registry 기반 재작성 - scheduled_rag_reindex_retry.md: 현행 코드에 해당 잡 없음 → _archive 이동 05_admin: - diary_reflection_pipeline.md: n8n 전제 제거, APScheduler + diary_generator.py 기준 재작성, /api/diary/generate(존재하지 않는 엔드포인트) 제거 Refs: DOCS#8 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
71 lines
3.4 KiB
Markdown
71 lines
3.4 KiB
Markdown
---
|
|
tags: [workflow, admin, diary, scheduler]
|
|
type: workflow
|
|
last_updated: 2026-04-06
|
|
---
|
|
|
|
# diary_reflection_pipeline 워크플로우
|
|
|
|
## 목적
|
|
매일 오전 2시에 전날의 로빙 일기를 자동 생성하고, DB에 저장하며, DOCS 레포에 마크다운 파일로 커밋·푸시한다.
|
|
|
|
## 아키텍처
|
|
- **스케줄러**: APScheduler (DB 기반). `db_loader.py`가 `scheduler_jobs` 테이블에서 `job_type=diary_generator` 잡을 로드하여 등록.
|
|
- **기본 스케줄**: `settings.DIARY_GENERATOR_SCHEDULE` = `0 2 * * *` (매일 02:00).
|
|
- **활성화 플래그**: `settings.DIARY_GENERATOR_ENABLED` (기본 `True`).
|
|
- **n8n 미사용**. systemd로 rb8001이 직접 실행.
|
|
|
|
## 코드 SSOT
|
|
- `rb8001/app/scheduler/jobs/diary_generator.py` — 잡 래퍼 + 일기 생성 로직
|
|
- `rb8001/app/services/diary/aggregator.py` — `DiaryAggregator` (데이터 집계)
|
|
- `rb8001/app/services/diary/generator.py` — `DiaryGenerator` (LLM 일기 생성)
|
|
- `rb8001/app/state/diary_repository.py` — `save_diary()` (DB 저장)
|
|
- `rb8001/app/router/diary_endpoint.py` — 일기 조회 API
|
|
- `rb8001/app/scheduler/db_loader.py` — DB 잡 로더 (`JOB_TYPE_MAP["diary_generator"]`)
|
|
|
|
## 흐름
|
|
|
|
```
|
|
APScheduler cron trigger (0 2 * * *)
|
|
→ db_loader가 등록한 guarded_job (schedule_policy 평가)
|
|
→ _run_diary_generator_with_logging()
|
|
→ _generate_diary()
|
|
1. draft_watcher 선행 실행 (non-blocking)
|
|
2. DiaryAggregator.aggregate(target_date, robeing_id) — 전날 활동 데이터 집계
|
|
3. DiaryGenerator.generate(target_date, robeing_id, aggregated_data) — LLM 일기 생성
|
|
4. save_diary() — DB 저장 (full_content, summary, dominant_emotion, stats)
|
|
5. _save_diary_to_git() — DOCS 레포에 마크다운 저장 + git add/commit/push
|
|
6. ActivityLogger.log_scheduler_job() — 스케줄러 작업 로그 기록
|
|
```
|
|
|
|
## 일기 조회 API (현행)
|
|
|
|
| 메서드 | 경로 | 설명 |
|
|
|--------|------|------|
|
|
| `GET` | `/api/diary/{target_date}?robeing_id=rb8001` | 특정 날짜 일기 조회 |
|
|
| `GET` | `/api/diary/list?robeing_id=rb8001&limit=100` | 일기 목록 조회 |
|
|
|
|
**주의**: `/api/diary/generate` 엔드포인트는 코드에 존재하지 않는다. 일기 생성은 APScheduler 잡이 내부적으로 `DiaryGenerator.generate()`를 직접 호출한다.
|
|
|
|
## 일기 저장 경로
|
|
- **DB**: `diary` 테이블 (`date`, `robeing_id`, `full_content`, `summary`, `dominant_emotion`, `stats`)
|
|
- **Git**: `$DOCS_REPO_PATH/book/700_for_robeing/diary/{YYYY-MM-DD}.md`
|
|
- `DOCS_REPO_PATH` 환경변수, 기본값: `$WORKSPACE_ROOT/robeing/DOCS`
|
|
|
|
## 선행 작업
|
|
- 일기 생성 전 `draft_watcher`를 실행하여 NAS 드래프트 변경사항을 activity_log에 기록한다 (실패 시 non-blocking).
|
|
|
|
## 실패 분기
|
|
- `DiaryGenerator.generate()`가 `None`을 반환하면 `RuntimeError` 발생.
|
|
- DB 저장 실패 시 에러 로그 + ActivityLogger에 `status=error` 기록.
|
|
- Git push 실패 시 에러 로그만 남기고 계속 진행 (non-blocking).
|
|
|
|
## 환경변수
|
|
- `DIARY_GENERATOR_ENABLED` — 일기 생성 활성화 여부 (settings 경유, 기본 `True`).
|
|
- `DIARY_GENERATOR_SCHEDULE` — cron 표현식 (settings 경유, 기본 `0 2 * * *`).
|
|
- `DOCS_REPO_PATH` — DOCS 레포 경로 (환경변수, 기본 `$WORKSPACE_ROOT/robeing/DOCS`).
|
|
- `ROBEING_ID` — 로빙 식별자 (settings 경유).
|
|
|
|
## 관련 문서
|
|
- [service_health_check (레거시, _archive 이동됨)](../_archive/service_health_check.md)
|