멱등성 — 두 번 눌러도 한 번만 결제되게 · 멱등 요청에도 재시도 예산이 필요하다 · 실습
멱등 요청에도 재시도 예산이 필요하다
목표
상태 코드·요청 안전성·최대 횟수·전체 시간 제한을 함께 지키는 실행기를 만듭니다.
왜 중요한가
정상 요청 한 번의 성공은 경계값과 장애 복구를 보장하지 않습니다. 이 실습은 각 함수의 계약을 작게 구현하거나 테스트한 뒤 실제 실행으로 연결합니다. 코드가 존재하는지나 보고서 문구만 보지 않고 결과·예외·저장 상태를 검사합니다. 앞 단계의 코드를 유지하며 다음 단계로 진행하세요.
단계
1. /root/work/idem-retry-budget-lab/service.py에서 retryable(status)는 429, 502, 503, 504에만 True를 반환하세요. 나머지 상태는 False입니다. 이 목록은 실습 정책이며 모든 서비스의 정답은 아닙니다. 첫 준비는 다음 명령으로 합니다.
mkdir -p /root/work/idem-retry-budget-labcp /opt/fixtures/practice_depth/idem-retry-budget-lab/* /root/work/idem-retry-budget-lab/cd /root/work/idem-retry-budget-lab2. /root/work/idem-retry-budget-lab/service.py에서 replay_safe(method, key=None)는 대소문자 무관 GET·HEAD·PUT·DELETE 또는 공백 아닌 key가 있는 POST만 True로 반환하세요. PATCH는 이 계약에서 허용하지 않습니다.
3. /root/work/idem-retry-budget-lab/service.py에서 remaining(deadline, now)는 deadline-now와 0 중 큰 값을 반환하세요. 인자는 단조 시계의 초 단위 실수입니다.
4. /root/work/idem-retry-budget-lab/service.py에서 backoff(attempt, base=0.5, cap=4.0)는 min(cap, base*2**attempt)를 반환하세요. attempt는 0~30, base·cap은 음수가 아니어야 하며 위반 시 ValueError입니다.
5. /root/work/idem-retry-budget-lab/service.py에서 jitter(delay, fraction)는 delay*fraction을 반환하세요. delay>=0, 0<=fraction<=1이어야 하며 위반 시 ValueError입니다.
6. /root/work/idem-retry-budget-lab/service.py에서 wait_delay(local, retry_after)는 local과 Retry-After 정수 초 중 큰 값을 반환하세요. None·음수·비정수·날짜 등 지원하지 않는 값은 0초로 해석합니다.
7. /root/work/idem-retry-budget-lab/service.py에서 can_attempt(attempts, maximum, wait, budget)는 attempts < maximum, wait>=0, budget>wait를 모두 만족할 때만 True입니다. attempts는 이미 수행한 총 호출 수입니다.
8. /root/work/idem-retry-budget-lab/service.py에서 execute(send, clock, sleep, method='GET', key=None, timeout=5.0, maximum=3, random_fraction=lambda:0.5)를 구현하세요. send(남은 초)는 {status: int, retry_after: 선택값}을 반환합니다. 처음 deadline을 고정하고 위 정책에 따라 재시도하며 더 못하면 마지막 응답을 반환합니다. timeout<=0 또는 maximum<1은 ValueError, 호출 직전 예산 소진은 TimeoutError입니다.
참고
- 패키지는 이미지에 설치돼 있습니다. 인터넷 연결이나 pip install은 필요하지 않습니다.
- 준비 복사는 최초 한 번만 하세요. 다시 복사하면 작업 파일이 초기화됩니다.
- 채점은 여러분의 service.py를 불러와 다른 id와 임시 저장소로 실행합니다. 결과를 상수로 박지 마세요.
- 각 단계 채점은 45초 안에서 실행됩니다. 무한 루프나 실제 대기를 만들지 마세요.
8단계
- 재시도할 응답을 좁힌다
- 요청을 다시 보내도 되는지 판단한다
- 하나의 마감 시각을 공유한다
- 백오프에 상한을 둔다
- 지터를 결정적으로 테스트한다
- 서버 대기보다 일찍 재시도하지 않는다
- 시도 횟수와 대기 예산을 함께 본다
- 가짜 시계로 실행기 전체를 검증한다