외부 거래소의 주문 상태값을 우리 OrderStatus 로 바꾸는 매핑에 새 값 PARTIALLY_CANCELED 를 넣어야 했다. order_status_map 테이블에 넣었는데 반영되지 않았다.
Table of contents
Open Table of contents
원인 — 코드에도 있던 같은 매핑
찾아보니 같은 매핑이 코드의 StatusMapper 상수 사전에도 들어 있었다. 테이블에도 있고 코드에도 있는데 읽는 쪽이 서로 달랐다.
체결 통보 수집기는 코드 사전을 읽고 관리 화면은 테이블을 읽는다. 그래서 한쪽에만 넣으면 다른 쪽은 그 값을 모른 채로 돈다.
검증 — 서로 다른 항목의 누락
두 곳을 나란히 놓고 비교하니 누락된 항목이 서로 달랐다. 어떤 값은 테이블에만 있고 어떤 값은 양쪽 다 없었다.
order_status_map 에만 있는 값이 오면 수집기는 처리를 못 하고 관리 화면은 처리한다. 같은 데이터가 시스템마다 다르게 보이는 상태이고 어느 쪽도 오류를 내지 않는다.
주의 — 반영 시점의 비대칭
더 미묘한 것은 반영 시점이었다. 테이블 변경은 즉시 반영되지만 코드 변경은 병합과 Jenkins 배포를 거친다.
그 사이에는 한쪽이 새 매핑이고 다른 쪽이 옛 매핑인 구간이 생긴다. 급할 때 order_status_map 만 고치고 배포를 미루면 그 구간이 길어진다.
조치 — 모으지 못하면 어긋남을 알린다
두 가지 방법이 있었다. 수집기가 시작할 때 테이블을 읽어 메모리에 올리고 캐시 무효화를 만들어 한 곳으로 모으는 것과, 당장은 양쪽을 함께 갱신한다는 규칙을 적고 두 곳을 비교하는 점검을 두는 것이다. 뒤쪽을 골랐다. 이유는 캐시 무효화가 수집기 재기동 절차를 바꾸는 일이라 리브랜딩 일정 안에 안 들어가서다. 대신 규칙을 사람이 지켜야 하는 것을 감수했고 그래서 점검을 Jenkins 빌드에 붙였다.
근본적으로는 한 곳으로 모으고 테이블을 정본으로 삼는 것이 맞다. 모으지 못했으면 최소한 어긋났다는 사실은 알아야 하기 때문이다.
새 상태를 만들기 전에 찾는 선례
매핑을 넣으면서 우리 쪽 OrderStatus 를 새로 만들지 않는 것도 확인했다. 우리 상태는 여섯 개로 정해져 있고 외부 값이 어디에도 안 맞아 보여도 늘리지 않는 편이 낫다.
PENDING_CANCEL 에 해당하는 값을 어디에 넣을지 고민하다 다른 거래소의 같은 성격 값이 어디로 가는지를 찾아 같은 곳으로 보냈다. 상태를 하나 늘리면 그것을 처리하는 모든 switch 를 다시 봐야 하므로 정합성이 새 표현보다 낫다.
이 작업은 인계받은 것이었는데 인계 문서에는 두 건을 넣으면 된다고 적혀 있었다. 실제로 조회하니 한 건은 이미 들어가 있었으므로 인계받은 절차는 실행 전에 현재 상태를 조회해 확인해야 했다.
정리
- 같은 매핑이
StatusMapper와order_status_map에 함께 있으면 서로 다른 항목을 누락한다 - 읽는 쪽이 다르면 같은 데이터가 시스템마다 다르게 보인다
- 어느 쪽도 오류를 내지 않으므로 비교하기 전에는 안 드러난다
- 테이블은 즉시 반영되고 코드는 배포를 거친다
- 그 사이에 한쪽만 새 매핑인 구간이 생긴다
- 한 곳으로 모으지 못하면 양쪽을 비교하는 점검을 둔다
- 새
OrderStatus를 만들기 전에 같은 성격의 선례를 찾는다 - 인계받은 절차는 실행 전에 현재 상태를 조회해 확인한다