Skip to content
isdnetworks
Go back

비슷해 보이는 엔드포인트 셋

20만 건이 넘는 대량 처리 요청을 받고 배치 엔드포인트가 있는지 찾았다.

Table of contents

Open Table of contents

증상 — 비슷한 이름 셋

경로 파일을 뒤졌다.

rg 'batch.*disconnect' routes/

셋이 나왔다.

/product/batch/distribution-disconnect
/product/batch/distribution-disconnect-and-pending-v2
/product/v2/force-disconnect

distribution-disconnectforce-disconnect 가 무엇이 다른지 경로만으로는 갈리지 않았다.

원인 — 이름으로 골랐다

두 번째가 맞아 보였다.

distribution-disconnect-and-pending-v2

v2 가 붙어 신 구조용이고 disconnect 까지 들어 있어 이것으로 하겠다고 했다.

그 자리에서 지적을 받았다. 실제 컨트롤러 본문을 확인하지 않았다는 것이었고 경로 파일만 봤을 뿐 그 경로가 어느 메서드를 부르는지도 안 봤다.

검증 — 셋을 다 읽었다

routes 가 가리키는 컨트롤러를 하나씩 열었다.

public function batchDisconnect(Request $request)
{
    foreach ($ids as $id) {
        $this->service->disconnectProductV1($id);   // ← 옛 경로
    }
}

첫 번째는 disconnectProductV1 을 부르는 옛 구조 전용이라 신 구조 대상에는 적용되지 않는다.

두 번째인 batchDisconnectAndPendingV2 가 내가 고른 것이었다.

public function batchDisconnectAndPendingV2(Request $request)
{
    foreach ($ids as $id) {
        $this->service->disconnectV2($id);
    }
}

disconnectV2 가 무엇을 하는지 그 아래까지 따라갔다.

public function disconnectV2($id)
{
    $result = $this->sendStopToMarket($id);       // 외부 요청 발송
    if ($result->isSuccess()) {
        $this->afterDisconnect($id);              // 후처리
    }
}

sendStopToMarket 으로 외부에 요청을 보내고 그것이 성공해야 afterDisconnect 가 돈다.

세 번째 forceDisconnectV2 는 달랐다.

public function forceDisconnectV2($id)
{
    // 외부 호출 없음
    $this->afterDisconnect($id);      // 바로 후처리
}

forceDisconnectV2 는 외부 호출 없이 바로 afterDisconnect 로 간다.

판단 기준 — 외부에 없는 대상

이번 대상은 마켓 쪽에 이미 없는 상품들이었다.

요청 발송  →  "그런 상품 없음"  →  실패

후처리가 실행 안 됨

두 번째로 돌리면 sendStopToMarket 이 반드시 실패해서 아무것도 정리되지 않는다.

세 컨트롤러를 나란히 놓으니 갈렸다.

① 옛 구조 전용        →  대상 불일치
② 외부 요청 필요       →  실패해서 후처리 안 됨
③ 외부 호출 없음      →  적합

이름으로는 두 번째가 맞아 보이는데 실제로 되는 것은 세 번째뿐이었다.

제약 — 본문에서 함께 나온 상한

세 컨트롤러를 읽으면서 공통점도 봤다.

foreach ($ids as $id) { ... }

셋 다 foreach 동기 반복이고 $ids 크기에 상한이 없었다.

20만 건을 한 번에 보내면 요청이 시간 초과로 끊기거나 메모리가 넘친다. 그래서 배치를 나눠 보내도록 계획을 고쳤는데 이것도 본문을 읽어야 나오는 제약이었다.

재발 방지 — 본문까지 읽는 규칙

경로 파일 검색으로 아는 것에는 경계가 있었다.

[알 수 있는 것]  이런 엔드포인트가 있다
[알 수 없는 것]  뭘 하나 / 어떻게 하나 / 제약이 뭔가

disconnect 라는 말이 셋에 다 들어 있을수록 위험한데 이름으로 고르게 되기 때문이다.

게다가 afterDisconnect 가 한 일은 되돌리기 어렵고 이번에는 20만 건이었다. 두 번째로 돌렸으면 전부 실패하고 왜 아무것도 안 됐는지 다시 조사했을 것이고 일부가 성공했으면 부분 처리 상태가 남았을 것이다.

그래서 엔드포인트를 고를 때 경로 파일만 보지 않고 컨트롤러 본문과 그것이 부르는 서비스 메서드까지 읽는 것을 규칙으로 적었다. 이름이 비슷한 것이 여럿이면 반드시 그렇게 한다.

정리


Share this post on:

Previous Post
정렬 없는 first가 엉뚱한 걸 복원한다
Next Post
지우고 다시 만드는 중에 멈추면 더 나빠졌다