[BE-02] DropReservationStore 게이트웨이 계약 (입장 게이트 + 완충)
작업 내용 (설계 의도)
변경 사항
Redis 입장 게이트(FR-8) + 완충(FR-7) + 1인 한도(FR-6) + 멱등을 감추는 domain gateway 계약을 신설한다(근거 TDD: ../TDD.md “인터페이스 시그니처”, ADR-001·ADR-003). SeatLockStore(domain gateway) 선례를 따른다. BE-03(도메인 서비스)·BE-04(구현체)가 이 계약을 공유한다. 파일 집합이 BE-01과 겹치지 않아 같은 wave 병렬 안전.
DropReservationStore(interface,domain/goods/gateway):seedIfAbsent(dropId, initialQuantity, ttl)·reserve(dropId, userId, quantity, perUserLimit, idempotencyKey): ReservationResult·confirmSuccess(...)·cancel(...)·remaining(dropId): Int?.ReservationResult(sealed interface):Admitted·AlreadyReserved·SoldOut·Throttled·PerUserLimitExceeded(limit).- 계약 의미 주석: reserve는 원자 판정(FR-8 소진 거부 먼저 → FR-7 완충 permit 획득), Admitted 시 permit 보유. confirmSuccess=성공(DECR 유지, permit 반납), cancel=실패(DECR·1인 카운트 복원, permit 반납).
- Redis 상세(키·TTL·Lua)는 이 티켓 범위 아님 —
private-redis-implementer후속. 이 티켓은 순수 interface·sealed 타입만.
의존
- 없음 (선행 병목)
다이어그램
클래스 의존
flowchart LR DropReservationStore -.->|반환| ReservationResult ReservationResult --> Admitted ReservationResult --> SoldOut ReservationResult --> Throttled ReservationResult --> PerUserLimitExceeded ReservationResult --> AlreadyReserved
테스트 케이스
- ReservationResult sealed의 5개 분기(Admitted/AlreadyReserved/SoldOut/Throttled/PerUserLimitExceeded)가 when 전수 분기로 처리된다
- PerUserLimitExceeded는 한도값(limit)을 노출한다
- DropReservationStore interface가 domain 레이어에 위치하고 infrastructure를 import하지 않는다 (컴파일·패키지 검증)