LabHub
学习 学习路径 课程

FastAPI — 타입이 곧 계약이다 · ETag로 덮어쓰기 충돌을 막는 API · 实验

ETag로 덮어쓰기 충돌을 막는 API

在 LabHub 中继续学习

목표

두 사용자가 같은 초안을 수정할 때 SQL 조건부 갱신과 HTTP 응답으로 유실을 막습니다.

왜 중요한가

정상 요청 한 번의 성공은 경계값과 장애 복구를 보장하지 않습니다. 이 실습은 각 함수의 계약을 작게 구현하거나 테스트한 뒤 실제 실행으로 연결합니다. 코드가 존재하는지나 보고서 문구만 보지 않고 결과·예외·저장 상태를 검사합니다. 앞 단계의 코드를 유지하며 다음 단계로 진행하세요.

단계

1. /root/work/fa-conditional-lab/service.py에서 init_db(path)는 SQLite 파일에 notes(id TEXT PRIMARY KEY, title TEXT NOT NULL, version INTEGER NOT NULL)를 생성하세요. 반복 호출해도 기존 데이터를 지우지 않습니다. 첫 준비는 다음 명령으로 합니다.

mkdir -p /root/work/fa-conditional-labcp /opt/fixtures/practice_depth/fa-conditional-lab/* /root/work/fa-conditional-lab/cd /root/work/fa-conditional-lab

2. /root/work/fa-conditional-lab/service.py에서 create_note(path, note_id, title)는 버전 1로 메모를 INSERT하고 커밋하세요. 같은 id는 sqlite3.IntegrityError로 거절하며 기존 제목을 덮어쓰지 않습니다.
3. /root/work/fa-conditional-lab/service.py에서 read_note(path, note_id)는 {id, title, version} 딕셔너리 또는 None을 반환하세요. SQL에 id를 문자열 연결하지 말고 바인딩합니다.
4. /root/work/fa-conditional-lab/service.py에서 etag(version)는 정수 버전을 큰따옴표까지 포함한 문자열로 반환하세요. 예: 버전 3은 문자열 '"v3"'입니다.
5. /root/work/fa-conditional-lab/service.py에서 parse_match(header)는 큰따옴표 안 v와 양의 십진 정수 하나인 태그만 받아 버전을 반환하세요. None, weak 태그, 와일드카드, 목록, v0 등은 ValueError입니다. 예: '"v12"' → 12.
6. /root/work/fa-conditional-lab/service.py에서 update_note(path, note_id, title, version)는 id와 version이 모두 일치할 때만 제목을 갱신하고 버전을 1 올리세요. 변경 행이 하나면 True, 없으면 False입니다. 동시 요청에도 승자는 하나여야 합니다.
7. /root/work/fa-conditional-lab/service.py에서 put_note(path, note_id, title, header)는 없는 id 404, 조건 누락 428, 지원하지 않는 조건·버전 불일치 412, 성공 204를 반환하세요. 거절 시 DB를 바꾸지 않습니다.
8. /root/work/fa-conditional-lab/service.py에서 create_app(path)는 GET /notes/{note_id}와 PUT /notes/{note_id}를 제공하세요. GET은 메모 JSON과 ETag, PUT은 {title: 1~100자 문자열}·If-Match를 받아 위 결과 코드로 빈 응답을 반환합니다. 빈 제목은 422, 없는 GET은 404입니다.

참고

8个步骤

  1. 버전을 가진 저장소를 만든다
  2. 첫 저장의 버전을 고정한다
  3. 없는 메모와 있는 메모를 구분한다
  4. 강한 ETag를 만든다
  5. 지원하는 조건 문법만 받는다
  6. 비교와 쓰기를 하나의 SQL로 묶는다
  7. 실패를 HTTP 결과로 분류한다
  8. 오래된 화면 저장을 HTTP로 재현한다