멱등성 — 두 번 눌러도 한 번만 결제되게 · 멱등 키를 지우면 보장도 끝난다 · 实验
멱등 키를 지우면 보장도 끝난다
목표
완료·진행 중 기록을 구분하고 보관 기간과 배치 정리를 구현합니다.
왜 중요한가
테이블이 커지자 오래된 멱등 키를 모두 삭제했다. 아직 결제 중인 요청의 기록도 사라졌고 재시도가 새 요청으로 들어왔다. 완료 응답의 보관 기간과 진행 중 작업의 소유권은 같은 만료 정책이 아니다. 정리는 단순 DELETE가 아니라 보장 범위를 바꾸는 상태 전이다.
단계
1. /root/work/idem-retention-lab/service.py에서 init_db(path)는 keys(id TEXT PRIMARY KEY,fingerprint TEXT NOT NULL,status TEXT NOT NULL,response TEXT,expires REAL NOT NULL)를 멱등 생성합니다.
처음 한 번 준비하세요. 기존 파일은 덮어쓰지 않습니다.
mkdir -p /root/work/idem-retention-labtest -e /root/work/idem-retention-lab/service.py || cp /opt/fixtures/ten_labs/idem-retention-lab/service.py /root/work/idem-retention-lab/service.pycd /root/work/idem-retention-lab2. /root/work/idem-retention-lab/service.py에서 reserve(path,key,digest,expires)는 없는 키를 pending,response=NULL로 넣고 True입니다. 기존 키는 만료와 관계없이 바꾸지 않고 False입니다.
3. /root/work/idem-retention-lab/service.py에서 finish(path,key,digest,response)는 일치하는 key·fingerprint이며 pending인 행만 response를 JSON으로 저장하고 done으로 바꿔 True, 나머지는 False입니다.
4. /root/work/idem-retention-lab/service.py에서 fetch(path,key,now)는 done이고 expires>now인 행의 response를 JSON 파싱해 반환합니다. 그 외 None입니다.
5. /root/work/idem-retention-lab/service.py에서 expired(path,now,limit=10)는 bool 제외 int 1~100인 limit를 검사합니다. done이고 expires<=now인 id를 id 오름차순으로 최대 limit개 반환합니다.
6. /root/work/idem-retention-lab/service.py에서 purge(path,now,limit=10)는 expired와 같은 limit 검증·조건·정렬로 후보를 고른 뒤 한 트랜잭션에서 삭제하고 삭제한 id 리스트를 반환합니다. pending은 지우지 않습니다.
7. /root/work/idem-retention-lab/service.py에서 counts(path)는 {pending:개수, done:개수}입니다. 해당 상태가 없어도 키와 0이 있어야 합니다.
8. /root/work/idem-retention-lab/service.py에서 retention_cycle(path,key)는 expires=10,digest='v1'로 예약하고 {receipt:1}로 완료합니다. now=10에서 purge 후 같은 키를 digest='v2',expires=20으로 새 예약해 그 결과 bool을 반환합니다. 함수는 빈 DB를 전제로 합니다.
참고
- 인터넷과 패키지 설치 없이 기존 lab-dev 환경에서 수행합니다.
- 각 단계는 45초 채점 예산 안에서 실행됩니다. 실제 sleep이나 네트워크 호출을 추가하지 마세요.
- 채점은 제출 모듈을 새로 불러오고 독립 입력과 임시 DB로 검사합니다. 예상값을 상수로 반환하는 대신 계약을 구현하세요.
- [FastAPI 공식 문서](https://fastapi.tiangolo.com/) · [pytest 공식 문서](https://docs.pytest.org/en/stable/) · [Python sqlite3](https://docs.python.org/3/library/sqlite3.html)
- 한계: 무한 기간 exactly-once 효과를 보장하지 않는다. 외부 시스템은 오래된 요청을 재전송할 수 있으므로 보관 기간은 제공자의 재시도 정책과 맞춰야 한다. abandoned pending을 복구하는 임대·보상 정책은 별도 실습의 책임이며, 이 정리 함수에서 추측해 지우지 않는다.
8个步骤
- 완료 여부와 만료를 분리한다
- 진행 중 키를 예약한다
- 현재 요청만 완료한다
- 유효한 완료 응답만 재생한다
- 정리 후보를 제한한다
- 선택과 삭제를 같은 트랜잭션에 둔다
- 상태별 개수를 실제로 센다
- 삭제 뒤 보장 범위가 끝남을 확인한다