Skip to content
isdnetworks
Go back

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

(수정됨)

지원을 끝낸 코인의 입금 주소 20만 건을 해제해 달라는 요청을 받고 배치 엔드포인트가 있는지 찾았다.

Table of contents

Open Table of contents

증상 — 비슷한 이름 셋

경로 파일을 뒤졌다.

rg 'batch.*release' routes.php

후보는 셋이었다.

/wallet/batch/address-release
/wallet/batch/address-release-and-pending-v2
/wallet/v2/force-release

address-release 와 force-release 가 무엇이 다른지 경로만으로는 갈리지 않았다.

원인 — 이름으로 골랐다

두 번째가 맞아 보였다.

address-release-and-pending-v2

v2 가 붙어 새 지갑 연동용이고 release 까지 들어 있어 이것으로 하겠다고 했다.

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

검증 — 셋을 다 읽었다

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

public function batchRelease(array $ids)
{
    foreach ($ids as $id) {
        $this->service->releaseAddressV1($id);   // ← 옛 지갑 연동
    }
}

첫 번째는 releaseAddressV1 을 부르는 옛 연동 전용이라 위탁 지갑 대상에는 적용되지 않는다.

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

public function batchReleaseAndPendingV2(array $ids)
{
    foreach ($ids as $id) {
        $this->service->releaseV2($id);
    }
}

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

public function releaseV2($id)
{
    $result = $this->sendReleaseToCustody($id);   // 위탁 지갑에 요청 발송
    if ($result->isSuccess()) {
        $this->afterRelease($id);                 // 후처리
    }
}

sendReleaseToCustody 로 지갑 쪽에 요청을 보내고 그것이 성공해야 afterRelease 가 돈다.

세 번째 forceReleaseV2 는 달랐다.

public function forceReleaseV2($id)
{
    // 지갑 호출 없음
    $this->afterRelease($id);      // 바로 후처리
}

forceReleaseV2 는 지갑 호출 없이 바로 afterRelease 로 간다.

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

이번 대상은 위탁 지갑 쪽에 이미 없는 주소들이었다. 지갑 서비스가 그 코인 지원을 끝내며 먼저 폐기한 것이다.

요청 발송  →  "그런 주소 없음"  →  실패
    ↓
후처리가 실행 안 됨

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

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

① 옛 연동 전용        →  대상 불일치
② 지갑 요청 필요       →  실패해서 후처리 안 됨
③ 지갑 호출 없음      →  적합

이름으로는 두 번째가 맞아 보이는데 두 번째 대신 세 번째를 골랐다. 이유는 지갑 쪽에 없는 주소에 대해 실제로 되는 것은 세 번째뿐이라서다.

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

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

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

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

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

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

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

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

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

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

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

정리


Share this post on:

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