Skip to content
isdnetworks
Go back

플래그 하나를 두 기능이 쓴다

잠금이 걸린 항목의 처리를 허용하는 변경이 배포됐다. 검증하다가 잠금 규모가 궁금해졌다.

Table of contents

Open Table of contents

증상 — 잠금이 5,673건

먼저 규모를 셌다.

SELECT COUNT(*), COUNT(DISTINCT provider_id) FROM products WHERE is_modify_lock = 1;
-- 5,673건 / 132개사

is_modify_lock 이 켜진 것이 132개사에 걸쳐 있었다.

is_modify_lock 이 무엇인지 처음에는 행사 상품 지정으로 봤다. 그런 기능이 있다는 것을 알고 있어서 그쪽으로 읽었는데 지적을 받았다.

원인 — 두 기능이 같은 컬럼을 썼다

실제 이력 문구를 대조했다.

SELECT log, COUNT(*) FROM histories
 WHERE historiable_id IN (...) GROUP BY log;

log 가 두 종류로 나왔다.

'잠금 설정 되었습니다.'
'행사 상품으로 설정되었습니다.'

같은 is_modify_lock 인데 histories 에 남은 문구가 다르다.

코드를 보니 서로 다른 두 어드민 기능이 같은 컬럼을 쓰고 있었다.

// 행사 상품 지정
POST /product/modify_lock
 $product->is_modify_lock = 1;

// 채널상품 잠금
POST /products/channel-lock-batch
 $product->is_modify_lock = 1;

modify_lockchannel-lock-batch 가 같은 자리에 값을 쓴다.

modify_lock 화면에서 행사 상품으로 지정하면 값이 1이 되고 channel-lock-batch 에서 잠금을 풀면 그 값이 0이 된다. 두 기능을 쓰는 사람이 다르면 서로 모른 채로 상대의 상태를 밟는다.

영향 범위 — 게이트가 넓었다

이 잠금이 무엇을 막는지 지점을 전수로 찾았다.

연동 해제 (2곳)
작업 생성
재고 동기화
가격 동기화

연동 해제 만 막는 것이 아니라 재고 동기화가격 동기화 까지 막고 있었다.

그러면 잠긴 채로 팔리고 있는 상품이 문제가 된다. 재고를 바꿔도 반영이 안 되고 가격을 바꿔도 반영이 안 되니 사실상 동결이다.

검증 — 위험 조합 2,256건

잠긴 것 전부가 위험한 것은 아니었다.

잠금 상태
+ 판매 중
+ 마켓 연동 살아 있음

이미 판매 중지 인 것과 마켓 연동이 없는 것은 동결이어도 영향이 없다.

셋이 겹치는 것만 세었다.

잠금만            5,673건
+ 판매 중 + 연동   2,256건 / 27개사 / 15채널

판매 중 과 연동 조건으로 좁히니 실제 대상이 5,673건에서 2,256건으로 갈렸다.

숫자를 세는 것이 이 조사에서 결정적이었다. 잠금 상품이 좀 있다는 말과 2,256건이 동결 상태로 판매 중이라는 말은 같은 사실인데 무게가 다르다.

결과 — 절반만 해소된 상태

배포된 변경을 다시 봤다.

차단 경로 4개 중
  연동 해제 2개    →  해소됨
  재고·가격 동기화  →  그대로

네 경로 중 연동 해제 둘만 열렸고 재고 동기화가격 동기화 는 그대로였다.

2,256건은 여전히 동결 상태로 남아 있다는 뜻이라 그것을 별도로 보고했다. 부분 수정이면 무엇이 남았는지를 따로 적어야 다음 사람이 다 된 것으로 읽지 않는다.

대응 — 컬럼을 나누는 제안

이 컬럼을 다루는 작업에는 규칙을 남겼다.

두 기능이 같은 플래그를 공유한다
한 화면의 토글이 다른 화면의 상태를 뒤집는다

값만 보면 어느 기능이 켠 것인지 알 수 없어서 histories 의 문구를 봐야 한다.

근본은 컬럼을 나누는 것이었다.

is_event_locked    행사 상품
is_channel_locked  채널 잠금

is_event_lockedis_channel_locked 로 갈라 두면 서로를 뒤집을 자리가 없어진다.

다만 읽는 자리를 전부 고쳐야 하는 큰 변경이라 별도 제안으로 적었다. 이력이 남아 있어 지금은 구분이 되지만 이력이 없었으면 어느 기능이 켠 값인지 영영 몰랐을 것이다.

정리


Share this post on:

Previous Post
상태를 바꾸는 게터
Next Post
없는 레코드를 영원히 기다린다