Skip to content
isdnetworks
Go back

다른 곳에 있던 방아쇠

(수정됨)

취소했는데 채널에 반영이 안 된다는 문의를 받았고 order_cancels.status 는 DONE 이었다. CancelService::cancel() 전체를 읽었는데 외부로 보내는 부분이 없었다.

Table of contents

Open Table of contents

배경 — 취소 코드에 없던 전송

취소 로직은 상태를 바꾸고 order_histories 를 남기고 재고를 되돌리는 데서 끝났다. 그 안에는 dispatch() 가 한 줄도 없었다.

그런데 평소에는 외부에 반영되고 있었으므로 다른 어딘가에서 그것을 부른다는 뜻이었다. 동작을 하는 코드를 아무리 읽어도 언제 일어나는지는 안 나오는 상황이었다.

검증 — 호출자를 역추적한 결과

두 가지 방법이 있었는데 취소 흐름을 화면부터 다시 따라 내려가는 것과 외부로 보내는 SendChannelCancelJob 이름으로 grep -rn 해 그것을 만드는 곳을 찾는 것이다. 뒤쪽을 골랐다. 이유는 동작을 하는 코드를 아무리 읽어도 언제 일어나는지는 안 나와서다. 대신 잡 이름이 바뀌었거나 동적으로 만들어지면 검색에 안 걸리는 것을 감수했다. RefundService 파일에서 나왔다.

환불이 완료될 때 외부 취소가 나가는 구조였고 취소 자체가 아니라 그다음 단계가 방아쇠였다. 동작을 하는 코드가 아니라 그 동작을 부르는 곳을 찾는 것이 이런 조사에서 훨씬 빠른 경로였다.

원인 — 방아쇠가 된 다음 단계

문제의 건을 다시 보니 취소는 DONE 이고 외부 연동은 실패인데 refunds 레코드가 아예 없었다. 방아쇠가 될 사건 자체가 일어나지 않은 것이다.

선행 데이터가 없으면 그 뒤의 동작은 실패한 것이 아니라 시작되지 않은 것이다. 실패로 보고 재시도를 걸었으면 아무 변화 없이 시도 횟수만 늘었을 것이다.

조치 — 선행 데이터가 없던 이유

이 주문은 거래가 종료된 곳의 것이라 payment_id 와 seller_id 가 NULL 이었다. 그러면 RefundService 가 진입 조건을 못 넘는다.

즉 이 건은 구조적으로 외부 연동이 불가능한 상태였다. 시스템 안에서 재시도로 풀리는 종류가 아니었으므로 외부 관리 화면에서 직접 처리해야 한다는 것을 회신에 적었다.

주의 — 확정과 추론의 구분

seller_id 가 비어 있는 것이 진입을 막은 원인이라는 것은 내 판단이고 코드로 확정하지는 못했다. 진입 조건을 전부 확인하려면 여러 경로를 봐야 했고 그 시점에는 거기까지 가지 못했다.

그래서 그 부분을 INVESTIGATION.md 에 추론이라고 명시해 적었다. 확정과 추론을 섞어 두면 나중에 이 기록을 근거로 다른 판단을 할 때 그 위에서 틀린다.

정리


Share this post on:

Previous Post
데이터로 가르는 책임 소재
Next Post
이름이 같은데 다른 것