# task-3018 — 유튜브 러너 순차처리 (Whisper 큐 적체 제거)

**레벨**: Lv.2 · **팀**: dev2-team (오딘) · **회장 승인 완료** (2026-08-25)
**저장소**: `Jeon-Jonghyuk/InsuWiki` (`/home/jay/projects/insuwiki`, 기본 브랜치 **master**)

## 배경 — t3011 로 러너를 배포하자 드러난 문제

**ANU 실측 (2026-08-25 20:19~20:43)**
```
러너 배포 직후 파이프라인 가동 → GPU 100% · 76°C · 그러나 wiki 카드 생성 0건

로그 (정확히 10분 간격 반복):
  20:19 / 20:29 / 20:39
    [WARNING] transcriber: Whisper 전사 실패:
              HTTPConnectionPool(host='localhost', port=8200): Read timeout
    [WARNING] 자막/STT 모두 실패 — 제목+설명 fallback
    [INFO]    wiki 카드 생성 스킵 (전사 없음/title_description)

★ 그런데 서버측 실측은 정반대다:
  20:43:10 다운로드 완료 → 20:43:38 전사 완료   (28초)
  20:43:38 다운로드 완료 → 20:44:02 전사 완료   (24초)
  → 전사 자체는 24~28초에 끝난다. large-v3 가 느린 게 아니다.

서버: services/whisper-gpu/server.py 에 `_gpu_lock = asyncio.Lock()` → 실질 동시성 1
클라이언트: transcriber.py `timeout=600` (10분)
```

**진단**: 러너가 앞 요청의 종결을 기다리지 않고 계속 밀어넣어 **큐가 적체**됐다.
뒤쪽 요청이 순서를 기다리다 10분 타임아웃에 걸렸다. 서버 처리량 문제가 아니라
**클라이언트가 무제한 적체를 만든 것**이 원인이다.

현재: ANU 가 파이프라인 정지 + whisper 서비스 재시작으로 큐를 비웠다. GPU 0%.

---

## 고칠 것

### ① 생산자 backpressure (본수정)
러너가 **각 Whisper 요청의 종결을 기다린 뒤에만** 다음 요청을 보낸다.
- 종결에는 **성공뿐 아니라 실패·타임아웃도 포함**한다. 실패했다고 다음을 즉시 밀어넣으면 같은 적체가 난다
- ★ 동시성을 1로 고정하는 것만으로는 불충분하다. **완료 대기(await)** 가 본질이다

### ② 서버측 큐 한도 (2차 방어선)
`services/whisper-gpu/server.py` 에 **즉시 거절형 큐 한도**를 둔다.
- 대기열이 한도를 넘으면 **기다리게 하지 말고 즉시 거절**(429 등)한다.
  기다리게 하면 지금과 같은 타임아웃 적체가 재현된다
- ★ 이 파일은 **workspace 저장소**(`/home/jay/workspace/services/whisper-gpu/`)다. InsuWiki 가 아니다.
  **교차 저장소 작업이므로 범위를 최소로** 하고, 손대기 전에 현재 구조를 확인하라

### ③ ★ fail-closed 를 유지하라 (건드리지 마라)
```
"wiki 카드 생성 스킵 (전사 없음/title_description)"
```
**이것은 옳은 동작이다.** 전사 없이 제목·설명만으로 카드를 만들면 쓰레기 데이터가 쌓인다.
이 판정을 없애거나 완화하지 마라.

---

## ★★ 파이프라인 재가동은 이 태스크에서 하지 마라
수정과 검증까지만 한다. **타이머를 다시 켜는 것은 ANU 가 검증 결과를 보고 별도로 판단**한다.
(현재 `insuwiki-youtube-pipeline.timer` = inactive. **이 상태를 유지하라**)

검증은 **타이머가 아니라 수동 1회 실행**으로 하라.

---

## 검증 (실측 강제)
1. **현재 적체 재현** — 수정 전 상태에서 요청을 연속으로 보내 큐가 쌓이고 타임아웃이 나는 것을 재현하라.
   ★ 재현 시 **GPU 를 오래 점유하지 마라**. 짧은 영상·소수 요청으로 하고, 끝나면 정리하라
2. **수정 후** — 같은 조건에서 **요청이 중첩 적체되지 않고** 순차 종결되는지 확인
3. **10분 타임아웃 로그 미재발** 확인
4. **fail-closed 유지** — 전사 실패 건에 대해 여전히 wiki 카드가 **생성되지 않는지** 확인
5. **정상 경로** — 전사 성공 시 wiki 카드가 **실제로 생성**되는지 확인(Firestore `documents`)
6. **봉인** — backpressure 를 제거하는 변이를 만들어 테스트가 FAIL 하는지 확인하고 복원하라

## 범위 · 금지
**수정 허용**: `scripts/youtube-pipeline/run_pipeline.sh` · `youtube_pipeline/transcriber.py` ·
`youtube_pipeline/main.py`(순차 제어부) · 관련 테스트 ·
`/home/jay/workspace/services/whisper-gpu/server.py`(②만, 최소 범위)

**금지**:
- **fail-closed 판정 완화·제거** (③)
- **파이프라인 타이머 재가동**
- `firestore_writer.py` · `summarizer.py` · `drive_uploader.py` 로직 변경 (t3001 결과물)
- **요약 규격 변경**(1,500~2,000자 핵심 논지 재구성) — 회장 확정
- `.github/workflows/**`(t3009 백업 결과물) · `functions/**` · `nextapp/**`
- GPU 를 장시간 점유하는 검증

## allowed_resources

```yaml
allowed_resources:
  paths:
    - "scripts/youtube-pipeline/**"
    - "/home/jay/workspace/services/whisper-gpu/server.py"
    - "memory/reports/task-3018.md"
  forbidden_paths:
    - "scripts/youtube-pipeline/youtube_pipeline/firestore_writer.py"
    - "scripts/youtube-pipeline/youtube_pipeline/summarizer.py"
    - "scripts/youtube-pipeline/youtube_pipeline/drive_uploader.py"
    - ".github/workflows/**"
    - "functions/**"
    - "nextapp/**"
  commands:
    - "bash"
    - "python3"
    - "systemctl"
    - "gh"
  merge_policy: "tiered"
  ttl_hours: 24
```

## ★ 세션 조기 종료 대책 (오늘 4건 발생 — 반드시 지켜라)
- **시작 즉시 작업 브랜치를 만들고 드래프트 PR 을 먼저 열어라.** 마지막 한 번의 긴 응답에
  보고를 몰아넣지 마라
- **단계가 끝날 때마다** 진행 기록을 보고서 파일 또는 PR 본문에 갱신하라
- 최종 보고는 **분할 출력**하라
- ★ **ANU 명세의 전제가 틀렸다고 판단되면, 그 전제를 따른 구현을 진행하지 말고
  반증 결과를 먼저 기록한 뒤 ANU 에 보고하라.** (오늘 ANU 명세 오류가 3건 있었고
  전부 봇이 실측으로 반증했다)

## 운영 계약
- `origin/master`(=`ac726de`) 기준 `git pull --ff-only` 후 시작
- ★ `gh` 호출 시 `GH_TOKEN="$BOT_GITHUB_TOKEN"` 주입 필수 (회장 개인 PAT 금지 — 감사기록 오염)
- 워크플로우 `/home/jay/workspace/prompts/DIRECT-WORKFLOW.md` · QC `/home/jay/workspace/teams/shared/QC-RULES.md`
- `WORKSPACE_ROOT=/home/jay/workspace` · `CHAT_ID=6937032012` · 수집자 key `ANU_KEY=c119085addb0f8b7`
- 완료 경로는 `finish-task.sh` 실행이 유일하다. 수동 `.done` 금지.

## 완료 조건 (DoD)
**동일 조건 재실행에서 Whisper 요청이 중첩 적체되지 않고 각 요청이 종결 후 다음으로 넘어가며,
10분 대기성 timeout 로그가 재발하지 않고, 전사 없는 건은 기존대로 wiki 카드가 생성되지 않는다.**

## 보고
**PR 생성까지가 범위다. 머지는 ANU 가 한다. 자동 머지 금지.**
`memory/reports/task-3018.md` 작성 후 표준 완료 콜백 등록. 콜백 프롬프트 **UTF-8 3900 bytes 이하**.
★ 봉투 첫 줄에 **"적체 제거 실증 여부 + fail-closed 유지 여부"** 를 담아라.