이미 판매중지된 상품들에 SUSPEND 작업을 channel_jobs 에 중복으로 넣어도 되는지를 판단해야 했다. 내 추정은 이미 중지 상태이므로 멱등이고 실제 요청은 안 나갈 것이라는 쪽이었다.
Table of contents
Open Table of contents
검증 — 코드가 반증한 추정
추정을 확인하려고 SuspendJobRunner 를 열었다. 채널 계열에 따라 LegacyClient 와 OpenApiClient 로 갈라지긴 하지만 양쪽 다 실제로 외부 API 를 호출하고 있었다.
status === 'SUSPENDED' 를 먼저 확인하는 분기가 없었고 그냥 보내고 있었다. 멱등이 아니라 넣는 건수만큼 매번 밖으로 나가는 구조였다.
로그가 마켓의 답이었다
이것을 알고 나니 다른 것이 설명됐다. channel_jobs.last_log 에 마켓 응답의 message 를 그대로 저장하고 있었다.
우리가 내부적으로 찍은 문구가 아니라 밖에서 온 답이라는 뜻이다. 그러면 이 로그를 마켓 반영 여부의 근거로 쓸 수 있다.
판단 기준 — 바뀐 판단
원래 질문으로 돌아가면 중복 삽입은 그 건수만큼 실제 요청을 만든다. 이미 성공한 건에 또 넣으면 불필요한 외부 호출이 나가고 호출 한도를 소모하며 마켓 쪽에 부하를 준다.
수만 건이면 무시할 수 없는 양이다. 대상 범위를 정할 때 이것을 고려해야 하고 멱등이라는 가정 위에서 범위를 잡으면 그만큼 요청이 나간다.
조치 — 좁힌 대상
두 가지 방법이 있었는데 SuspendJobRunner 에 상태 확인 분기를 넣어 배포한 뒤 전부 넣는 것과 지금 코드 그대로 두고 last_log 로 이미 성공한 건을 대상에서 빼는 것이다. 뒤쪽을 골랐다. 이유는 대량 작업이 오늘이고 배포는 다음 주라서다. 대신 다음에 같은 작업을 하는 사람도 대상을 직접 좁혀야 하는 것을 감수했고 분기 추가는 백로그에 넣었다. 로그가 마켓의 답이므로 그 조건이 유효하다.
만약 그 로그가 내부 마킹이었으면 이 조건을 믿을 수 없었을 것이다. 로그의 출처를 확인한 것이 대상 조건의 근거가 됐다.
주의 — 두 갈래 경로와 확인 항목
코드에서 하나 더 봤는데 채널 계열에 따라 LegacyClient 와 OpenApiClient 로 간다는 점이었다. 경로가 다르면 응답 형식도 다를 수 있으므로 message 필드가 양쪽 다 있는지와 같은 뜻인지를 확인해야 한다.
이번에는 둘 다 같은 필드를 담고 있었지만 채널을 추가할 때 이 가정이 깨질 수 있다. 이런 판단에서 볼 것을 정리하면 그 작업이 외부로 나가는지와 나가기 전에 상태를 확인하는 분기가 있는지와 로그가 내부 것인지 외부 것인지 셋이고 두 번째가 없으면 대량 작업 전에 대상을 미리 좁혀야 한다.
정리
- 작업이 마킹만 하는지 실제 외부 호출을 하는지 코드로 확인한다
- 멱등일 것이라는 판단은 추정이다
- 코드를 열면 금방 확인된다
- 나가기 전에 상태를 확인하는 분기가 없으면 매번 나간다
- 대량 삽입은 그 건수만큼 실제 요청이 나간다
last_log가 외부 응답이면 반영 여부의 근거로 쓸 수 있다- 브로커 경로가 갈리면 응답 형식 가정을 확인한다
- 상태 확인 분기가 없으면 대상을 미리 좁힌다