feat: BAT-025 add portfolio ledger manual metadata migration

This commit is contained in:
2026-07-15 17:58:18 +09:00
committed by Hermes Agent
parent 600375beca
commit 1909caa22c
4 changed files with 407 additions and 0 deletions
@@ -0,0 +1,130 @@
# 운영 적용 런북: REQ-057 — portfolio_ledger 수동 장부 메타데이터 migration
- Batch: BAT-025
- Discovery: dcy-012
- Date: 2026-07-15
- 결재 게이트: REQ-057 완료 승인 및 release 결재 필수
- 작업 예상 시간: 약 20~40분
---
## 전제 조건
- DB 백업 완료
- `PORTFOLIOHUB_DB_ENABLED=true` 및 DB 접속 환경변수 설정
- 대상 DB는 `alembic current`로 `20260628_0027` 상태(또는 그 이전 배포 라인)에서 진행
- 새 코드 배포는 `alembic upgrade 20260715_0028` 완료 + 검증 성공 및 `M5 Release` 결재 후에만 수행
> 주의: 운영 DB는 본 배치에서 실제 upgrade/runbook 실행 대상을 만들지 않는다. 아래는 실운영 적용 체크리스트이다.
---
## 0) 사전 점검
```bash
export TIMESCALEDB_HOST=<DB_HOST>
export TIMESCALEDB_PORT=<DB_PORT>
export TIMESCALEDB_NAME=<DB_NAME>
export TIMESCALEDB_USER=<DB_USER>
export TIMESCALEDB_PASSWORD=<DB_PASS>
export PORTFOLIOHUB_DB_ENABLED=true
alembic heads
alembic current
```
- `alembic heads`에는 구현 시점 head `20260715_0028`가 확인되어야 한다.
- `alembic current` 값이 `20260715_0028`이면 이미 마이그레이션 적용 완료 상태다.
## 1) 프리체크
### 1-1. 대기 중인 락/액티브 커넥션
```sql
SELECT pid, usename, application_name, state, wait_event_type, wait_event, query
FROM pg_stat_activity
WHERE query ILIKE '%portfolio_ledger%'
AND state != 'idle';
```
- 결과는 반드시 비어 있거나 승인된 윈도우에서만 허용.
### 1-2. 대상 스키마 및 데이터 건수
```sql
-- 현재 컬럼 상태
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_name = 'portfolio_ledger'
AND column_name IN ('source', 'target_ledger_entry_id', 'confirmation_evidence', 'actor_user_id')
ORDER BY column_name;
-- 기존 행 수(증적)
SELECT COUNT(*) AS rows FROM portfolio_ledger;
```
- `source`가 이미 없거나 NULL 허용 상태여도 업그레이드 실행 전/후로 수렴 가능.
---
## 2) 마이그레이션 실행
```bash
alembic upgrade 20260715_0028
```
### 수신 메시지 예시
- 정상: `Running upgrade ...` 형태로 revision 로그 출력
- 실패: 즉시 종료되며 partial 변경 여부는 로그로 확인
---
## 3) 사후 검증
```sql
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_name = 'portfolio_ledger'
AND column_name IN ('source', 'target_ledger_entry_id', 'confirmation_evidence', 'actor_user_id')
ORDER BY column_name;
-- source backfill 결과(0이어야 함)
SELECT COUNT(*) AS null_source_rows
FROM portfolio_ledger
WHERE source IS NULL;
SELECT COUNT(*) AS rows_after FROM portfolio_ledger;
SELECT column_name, is_nullable
FROM information_schema.columns
WHERE table_name = 'portfolio_ledger' AND column_name = 'source';
SELECT column_default
FROM information_schema.columns
WHERE table_name = 'portfolio_ledger'
AND column_name = 'source';
```
- 기대치: `source`가 `NOT NULL`, `DEFAULT 'broker'`, `null_source_rows = 0`
- `rows_after` 값은 프리체크 시점과 일치해야 한다.
- `alembic current`가 `20260715_0028`로 일치해야 한다.
```bash
alembic current
```
---
## 4) 실패 대응 (Forward-only)
- 업그레이드 실패 시 바로 이전 코드로 rollback은 허용하되, 본 migration에서 추가된 4개 컬럼은 운영에서 자동 삭제하지 않는다.
- 필요한 경우 운영 담당과 협의하여 수동 복구 계획을 수립한다.
- 필수 검토 항목: 대상 DB 백업 상태, 실행 로그, 에러 스택, 락/동시 접속 상태
---
## 5) 운영 활성화 조건
- 위 사후 검증(`alembic current`/schema/row count/source null 없음) 완료
- API smoke(REQ-056 manual ledger) 통과
- release 결재 완료
- 위 조건 충족 시 신규 코드 재시작 및 API 활성화 수행