# 운영 가이드

## 빌드 상태

- `queued`: 대기
- `running`: 워커 실행 중
- `succeeded`: 성공
- `failed`: 실패
- `cancel_requested`: 취소 요청
- `cancelled`: 취소됨
- `retry_wait`: 자동 재시도 대기

실패 작업은 `attempts < max_attempts`이고 오류가 재시도 가능할 때 지수형 지연으로 다시 대기합니다.

## 출시 상태

- `queued`: 업로드 대기
- `running`: 외부 스토어 통신 중
- `succeeded`: 바이너리 업로드 또는 Google Edit 커밋 완료
- `failed`: 실패

출시 작업은 외부 API의 멱등성이 빌드 작업보다 약하므로 기본 구현에서는 자동 재시도하지 않습니다. 실패 원인을 확인하고 새 출시 작업을 생성하십시오.

## 워커 분리

Android/Linux:

```dotenv
WORKER_ID=android-worker-01
PLATFORM_ALLOWLIST=android
WORKER_CONCURRENCY=1
RELEASE_WORKER_ENABLED=true
```

iOS/macOS:

```dotenv
WORKER_ID=ios-mac-01
PLATFORM_ALLOWLIST=ios
WORKER_CONCURRENCY=1
RELEASE_WORKER_ENABLED=true
```

릴리스 워커는 `RELEASE_PROVIDER_ALLOWLIST`로 Google Play와 App Store 작업을 구분합니다. Linux 워커에는 `google_play`, macOS 워커에는 필요한 경우 `app_store`를 지정하십시오. 동일 provider 워커를 여러 대 띄울 수 있으며 MariaDB 잠금으로 한 작업만 선점합니다.

## 청소 정책

- 성공한 실제 빌드 작업공간: 즉시 삭제
- DRY RUN 작업공간: 확인을 위해 유지
- 실패 작업공간: 현재 기본 구현은 실제 빌드에서도 `finally`에서 삭제하므로, 디버깅 보관이 필요하면 정책 옵션 추가
- 빌드·출시 로그: 최소 90일
- 산출물: 요금제에 따라 30~365일
- 임시 Apple 개인 키: 작업 종료 즉시 삭제

## 백업

- MariaDB 일일 전체 백업과 binlog
- `runtime/artifacts` 객체 스토리지 복제
- 앱 설정 스키마와 Flutter 템플릿 Git 태그
- `APP_MASTER_KEY`와 서명키는 일반 DB 백업과 분리

## 모니터링

- `/health`
- 대기 작업 수와 최장 대기시간
- 15분 이상 실행 작업
- 빌드 및 출시 실패율
- 디스크 사용량
- Flutter/Xcode/Gradle/JDK 버전 변화
- 외부 스토어 API 오류율
- `store_connections.last_verified_at`
- `release_jobs.locked_at` heartbeat 정체

## 장애 복구

- 빌드: `locked_at`이 오래된 작업을 `retry_wait`로 복구
- 출시: 오래 실행된 작업은 자동 재업로드하지 않고 `failed` 처리합니다. 외부 스토어에서 실제 수락됐는지 확인한 뒤 새 작업을 등록해야 합니다.
- DB와 산출물 불일치: `build_artifacts.sha256`과 실제 파일 해시 비교
