LabHub
学习 学习路径 课程

FastAPI — 타입이 곧 계약이다 · 요청이 실패해도 자원을 닫는다 · 实验

요청이 실패해도 자원을 닫는다

在 LabHub 中继续学习

목표

시작·종료·예외 경로를 분리하고 FastAPI lifespan을 실제로 실행합니다.

왜 중요한가

테스트는 통과했지만 운영 재시작 때 연결이 남았다. TestClient를 context manager 없이 사용해 시작·종료 코드가 실행되지 않았던 것이다. 정상 응답 한 번을 보는 테스트만으로는 앱이 자원을 언제 열고 닫는지 알 수 없다. 여기서는 외부 연결 대신 이벤트를 기록하는 작은 자원으로 생명주기를 관찰한다.

단계

1. /root/work/fa-resource-lifecycle-lab/service.py에서 new_resource()는 {open:False, events:[]}인 새 딕셔너리이며 호출끼리 events를 공유하지 않습니다.

처음 한 번 준비하세요. 기존 파일은 덮어쓰지 않습니다.

mkdir -p /root/work/fa-resource-lifecycle-labtest -e /root/work/fa-resource-lifecycle-lab/service.py || cp /opt/fixtures/ten_labs/fa-resource-lifecycle-lab/service.py /root/work/fa-resource-lifecycle-lab/service.pycd /root/work/fa-resource-lifecycle-lab

2. /root/work/fa-resource-lifecycle-lab/service.py에서 start(resource)는 이미 열려 있으면 ValueError, 아니면 open=True로 바꾸고 events에 'open'을 추가합니다.

3. /root/work/fa-resource-lifecycle-lab/service.py에서 stop(resource)는 열려 있을 때만 open=False로 바꾸고 'close'를 events에 추가합니다. 이미 닫혀 있으면 그대로 둡니다.

4. /root/work/fa-resource-lifecycle-lab/service.py에서 read(resource)는 닫혀 있으면 RuntimeError, 열려 있으면 {ready:True}를 반환합니다.

5. /root/work/fa-resource-lifecycle-lab/service.py에서 scope(resource)는 contextmanager입니다. 진입 시 start, 블록 안에는 resource를 yield하고 블록의 성공·실패 모두 stop으로 닫습니다. 블록 예외는 전파합니다.

6. /root/work/fa-resource-lifecycle-lab/service.py에서 lifespan_for(resource)는 asynccontextmanager 함수 lifespan(app)을 반환합니다. scope(resource) 안에서 app.state.resource를 설정하고 yield합니다.

7. /root/work/fa-resource-lifecycle-lab/service.py에서 create_app(resource)는 lifespan_for를 사용합니다. GET /ready는 app.state.resource를 read한 결과를 반환합니다. context 종료 시 자원을 닫아야 합니다.

8. /root/work/fa-resource-lifecycle-lab/service.py에서 exercise(resource, fail=False)는 with TestClient(create_app(resource)) 안에서 GET /ready를 호출합니다. fail=True면 그 안에서 RuntimeError를 내고, 아니면 응답 JSON을 반환합니다. 두 경우 모두 자원이 닫혀야 합니다.

참고

8个步骤

  1. 자원 상태를 독립적으로 만든다
  2. 중복 시작을 거절한다
  3. 종료를 멱등하게 만든다
  4. 닫힌 자원의 사용을 막는다
  5. 예외 경로에 finally를 둔다
  6. 앱 수명주기와 자원을 연결한다
  7. 준비 상태를 실제 요청으로 읽는다
  8. 요청 이후의 실패도 정리한다