Skip to content

링크 등록 재시도가 한도를 깎고 409 로 실패하는 문제 해소 #973

Description

@m-a-king

응답이 유실된 뒤 클라가 같은 URL 로 재시도하면 두 가지가 어긋난다.

  1. 한도만 깎인다. 차감(ItemQuotaGuard.consume)이 중복 판정(WishPersistenceService.persist 안쪽)보다 앞에 있어, 409 로 끝나는 재시도도 몫을 소비한다. 사용자는 담지도 못한 채 한도를 잃고 그 몫은 돌아오지 않는다.
  2. 어느 위시인지 알 수 없다. 409 를 받은 클라는 "이미 담겨 있다"는 사실만 알 뿐 그 위시를 특정하지 못해, "보러가기" 같은 안내를 하려면 목록을 다시 조회해야 한다. 지금 ApiResponseBody.fail()data = null 로 고정이라 에러 응답이 맥락을 실어 나를 수 없기 때문이다.

같은 구조가 토너먼트 링크 담기(POST /tournaments/{tournamentId}/items/link)에도 있다. 409 와 오너 몫 차감이 같은 순서다.

무엇을

  1. 한도 차감을 중복 판정 뒤로 옮긴다. 409 로 거부되는 요청이 몫을 깎지 않는다.
  2. 409 응답에 기존 항목을 동봉한다. data 를 신규 등록 응답과 같은 모양으로 두어, 클라가 status 로 "새로 담김 / 이미 있음"만 가르고 카드는 같은 코드로 그리게 한다.

응답 계약

케이스 status code data
새로 담김 201 null WishItemResponse
이미 담긴 상품 409 WISH-005 WishItemResponse (기존 위시)
한도 소진 429 한도 code null
  • 토너먼트 링크 담기도 같은 결로 409 에 tournamentItemId 를 실어 대칭을 맞춘다.
  • 하위 호환이다. status 와 code 는 그대로고 data 가 더해질 뿐이라, 409 를 받던 기존 클라는 그대로 동작한다.
  • 차감이 판정 뒤로 가면서 status 우선순위가 하나 바뀐다. 지금은 한도를 먼저 보므로 이미 담긴 상품이어도 몫이 없으면 429 가 나가지만, 앞으로는 409 가 나간다. 중복은 한도와 무관한 사실이라 이쪽이 정확하다.

검토했으나 채택하지 않은 안

409 를 200 get-or-create 로 바꾸는 안. 이미 담긴 상품을 또 담으려는 것은 리소스 상태와의 충돌이라 409 가 의미상 맞고, "에러에 data 를 못 싣는다"는 구현 제약 때문에 status 의미를 왜곡하는 것은 본말전도다.

#470 이 from-play-link 를 409 에서 200 으로 바꾼 것과는 성격이 다르다. 클론 생성은 여러 번 해도 되는 행위라 재호출이 정상 흐름이지만, 같은 상품을 위시에 두 번 담는 것은 도메인상 막아야 할 상태다.

딸려오는 변경

  • ApiResponseBody.fail() 에 data 를 받는 오버로드 추가. 이 프로젝트의 모든 에러 응답이 지금까지 data: null 이었으므로, "에러도 맥락 데이터를 실을 수 있다"는 첫 선례가 된다.
  • 예외가 그 데이터를 나를 수 있어야 한다(WishException.alreadyExists(existing) 형태). 인자 없는 고정 메시지 팩토리라는 기존 결과 달라지는 지점이라 리뷰에서 함께 볼 것.
  • *Api 문서의 409 응답 스키마 갱신.

범위 밖

  • presign 발급 재시도의 한도 누수: 요청 본문이 contentTypes 뿐이라 자연 키가 약하다. 클라가 이미지 해시를 실어 보내는 content-addressed key 설계가 선행돼야 한다.
  • 스케줄러 중복 실행(WeeklyReport), extractor 재시도 비용도 별건이다.

연관: #910(차감의 양을 정밀화, 축이 다름), #470(검토했으나 성격이 다른 선례)

Metadata

Metadata

Assignees

Labels

fix외부 가시적 결함 수정

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions