Skip to content

fix: 스냅샷 UNIQUE(date) 단독 제약 재구축 + 저장 실패 전파#439

Merged
easygap merged 1 commit into
mainfrom
fix/snapshot-unique-migration
Jul 6, 2026
Merged

fix: 스냅샷 UNIQUE(date) 단독 제약 재구축 + 저장 실패 전파#439
easygap merged 1 commit into
mainfrom
fix/snapshot-unique-migration

Conversation

@easygap

@easygap easygap commented Jul 6, 2026

Copy link
Copy Markdown
Owner

무엇

kr_pocket 첫 실사이클이 적발한 구버전 스키마 결함 수정 + 그 결함이 드러낸 거짓 SNAPSHOT_SAVED 수정.

발견 경위 (실측)

kr_pocket 첫 사이클(2026-07-06 12:27)에서 매수는 성공했는데 스냅샷 저장이 UNIQUE constraint failed: portfolio_snapshots.date로 실패. 원인: account_key 도입 전 스키마의 UNIQUE (date) 단독 제약이 운영 DB에 남아 있었음(ALTER ADD COLUMN 마이그레이션은 제약을 못 바꿈). 지금까지 계정이 하나라 드러나지 않다가, 두 번째 바스켓이 같은 날 스냅샷을 쓰는 최초의 순간 충돌 — 이후 매일 조용히 유실될 상태였습니다.

부수 발견: save_portfolio_snapshot이 실패를 삼키고 호출부는 무조건 True를 반환해, 관측성이 거짓 SNAPSHOT_SAVED 이벤트를 기록했습니다(실제 DB엔 행 없음).

수정

  1. _migrate_snapshot_unique_constraint (models.py, init_database에서 호출): SQLite는 인라인 UNIQUE 삭제 불가 → 표준 재구축(rename → 신 스키마 create_all → INSERT OR IGNORE 복사 → 행수 검증 → 구 테이블 삭제). 멱등이며 중간 중단 시 다음 초기화에서 legacy 테이블을 감지해 복사부터 재개. 검증 실패 시 legacy 보존 + 예외(조용히 안 넘어감).
  2. 저장 성공 전파: save_portfolio_snapshot → boolsave_daily_snapshot → boolsave_daily_nav_snapshot이 그대로 전파 — 저장 실패가 SNAPSHOT_SKIPPED(warning)로 정직하게 기록되고 커버리지 결측 경보가 잡는다.

운영 적용 완료

  • 사전 백업 확인(일일 백업 + 수동 사본) 후 운영 DB에 적용: 18행 보존, 복합 유니크(account_key, date) 확인.
  • kr_pocket 사이클 재실행(재시도 크론과 동일한 자기치유) → 트랙 개시 확인: 스냅샷 7/6 총 300,126원, KODEX 200 1주 보유, 누적 +0.04%.

테스트

  • tests/test_snapshot_unique_migration.py: legacy DDL 재현 → 재구축 후 행 보존 + 두 계정 같은 날 저장 가능 + 같은 계정 같은 날은 여전히 차단 + 신 스키마 멱등 + rename 직후 중단 재개.
  • 전체 스위트 통과.

kr_pocket 첫 실사이클이 적발한 결함: account_key 도입 전 스키마의
UNIQUE(date) 단독 제약이 운영 DB에 남아 있어(ALTER ADD COLUMN은 제약을
못 바꿈), 두 번째 바스켓이 같은 날 스냅샷을 쓰는 최초의 순간
IntegrityError로 조용히 유실됐다. 계정이 하나였던 지금까지는 드러날 수
없던 결함이다.

수정 1 — _migrate_snapshot_unique_constraint(init_database에서 호출):
SQLite는 인라인 UNIQUE 삭제가 불가하므로 표준 재구축(rename → 신 스키마
create_all → INSERT OR IGNORE 복사 → 행수 검증 → 구 테이블 삭제).
멱등이며 rename 직후 중단돼도 다음 초기화가 legacy 테이블을 감지해
복사부터 재개한다. 검증 실패 시 legacy 보존 + 예외.

수정 2 — 저장 성공 전파: save_portfolio_snapshot이 실패를 삼키고
호출부가 무조건 True를 반환해 관측성이 거짓 SNAPSHOT_SAVED를 기록했다.
repo(bool) → portfolio_manager(bool) → save_daily_nav_snapshot 전파로
실패가 SNAPSHOT_SKIPPED(warning)와 결측 경보에 정직하게 잡히게 했다.

운영 적용 완료: 사전 백업 확인 후 재구축(18행 보존, 복합 유니크 확인),
kr_pocket 사이클 재실행으로 트랙 개시(스냅샷 7/6, KODEX200 1주).

테스트: legacy DDL 재현 재구축·행 보존·두 계정 같은 날 허용·같은 계정
차단·멱등·중단 재개. 전체 스위트 1631 통과.
@easygap easygap merged commit 92f5163 into main Jul 6, 2026
1 check passed
@easygap easygap deleted the fix/snapshot-unique-migration branch July 6, 2026 03:37
easygap added a commit that referenced this pull request Jul 6, 2026
fix: 스냅샷 UNIQUE(date) 단독 제약 재구축 + 저장 실패 전파
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant