[INFRA-08] reseed 배치 — 10분 주기 멱등 synthetic 복원

작업 내용 (설계 의도)

변경 사항

근거 TDD: ../TDD.md “실패 경로”, ADR-002. FR-3. 소진성 자원을 synthetic 범위에만 멱등 복원해 곡선 붕괴 방지. 관측 대상 앱에 요청 부하 0.

  • qa/load/reseed/reseed.sh(신규) — 10분 주기 loop. synthetic ID 범위에만:
    • 재고: UPDATE stocks SET quantity=baseline WHERE product_id IN (synthetic 풀)(절대 복원).
    • 슬롯: synthetic 예약(booking) 정리로 capacity 가용 복원(synthetic user_id 900000+ 범위 한정 soft-delete/정리).
    • 좌석: synthetic ticket_order 정리, Redis 좌석 락은 300s TTL 자연 만료에 위임.
    • 심야(배율 최저) 1회 synthetic 누적분 전체 정리.
  • qa/load/reseed/reseed.sql(신규) — 위 복원 SQL. 청크·jitter로 10분 윈도 내 분산(순간 write 스파이크 금지, NFR).

롤백: reseed 컨테이너만 stop(곡선은 read 위주라 즉시 붕괴 아님).

의존

  • INFRA-03 (synthetic ID 범위·baseline 계약)

다이어그램

처리 흐름

sequenceDiagram
    participant Cron as reseed loop(10분)
    participant DB as MySQL(synthetic)
    participant R as Redis
    Cron->>DB: stock quantity=baseline (청크·jitter)
    Cron->>DB: synthetic 예약/주문 정리 → 슬롯 복원
    Cron->>R: (좌석 락은 TTL 자연 만료)
    Cron->>Cron: 다음 주기 대기

테스트 케이스

  • synthetic stock을 소진 상태로 만든 뒤 reseed 실행하면 quantity가 baseline으로 복원된다.
  • reseed를 2회 연속 실행해도 재고가 baseline을 초과하지 않는다(멱등 절대 복원, 드리프트 없음).
  • reseed가 synthetic 범위 밖(실사용자 데이터)을 UPDATE하지 않는다(범위 밖 변경 0건).
  • 복원 write가 10분 윈도 내 청크로 분산되어 순간 부하 스파이크를 만들지 않는다.
  • 일부 SQL 실패 시 다음 주기 재실행으로 자동 수렴하고 트래픽이 중단되지 않는다.