리뷰 대상이 각각 플래그 1개만 있을 때 Score_to_hide_post가 0으로 변합니다

요약

score_to_hide_post0으로 떨어질 수 있습니다. 이는 백그라운드 작업인 Jobs::ReviewablePriorities가 백분위수 쿼리가 행을 반환하지 않을 때 priority_#{priorities[:high]}0으로 쓰기 때문입니다. 이 작업은 reviewable_count >= 15일 때 트리거되지만, 백분위수 계산에는 HAVING COUNT(*) >= :target_count(여기서 target_count는 일반적으로 2) 조건을 충족하는 reviewable만 포함됩니다. 대부분의 reviewable이 하나의 플래그만 가지고 있다면, 백분위수 서브쿼리는 아무것도 반환하지 않아 → high0이 되고 → score_to_hide_post = ((high * ratio) * scale).truncate(2)0으로 계산됩니다. 이로 인해 숨김 기준선이 0으로 붕괴되어 잘못된 숨김 동작이 발생합니다.


출처 (관련 코드/사실)

  • score_to_hide_post는 다음을 통해 계산됩니다:
score_to_hide_post = ((high.to_f * ratio) * scale).truncate(2)
  • high는 플러그인 스토어에서 읽힙니다:
PluginStore.get("reviewables", "priority_#{priorities[:high]}")
  • 해당 플러그인 스토어 항목은 시스템 작업인 Jobs::ReviewablePriorities에 의해 기록됩니다.
    이 작업은 다음 조건에서 실행됩니다:
reviewable_count = Reviewable.approved.where("score > ?", min_priority_threshold).count
return if reviewable_count < self.class.min_reviewables

여기서 self.class.min_reviewables15입니다.

  • 이 작업은 SQL을 사용하여 high를 계산합니다:
SELECT COALESCE(PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY score), 0.0) AS medium,
       COALESCE(PERCENTILE_DISC(0.85) WITHIN GROUP (ORDER BY score), 0.0) AS high
FROM (
  SELECT r.score
  FROM reviewables AS r
  INNER JOIN reviewable_scores AS rs ON rs.reviewable_id = r.id
  WHERE r.score > :min_priority AND r.status = 1
  GROUP BY r.id
  HAVING COUNT(*) >= :target_count
) AS x

여기서 :target_count는 일반적으로 2입니다.


근본 원인

함께 갭을 생성하는 두 개의 서로 다른 임계값이 있습니다:

  1. 작업은 min_priority_threshold를 초과하는 reviewable이 최소 min_reviewables(15)개 이상일 때 트리거됩니다 — 이는 :target_count 요구 사항을 무시한 거친 카운트입니다.
  2. 그러나 high를 생성하는 백분위수 계산에는 COUNT(*) >= :target_count(즉, 최소 2개의 reviewable_scores)를 가진 reviewable만 포함됩니다. 많은 reviewable이 각각 플래그가 하나씩만 있다면, 서브쿼리는 행을 반환하지 않고 백분위수는 폴백 값인 0.0을 반환합니다.

따라서 작업은 실행될 수 있습니다(거친 카운트 기준 reviewable이 15개 이상이기 때문에) 하지만 백분위수 집계에는 자격을 갖춘 행이 없습니다(HAVING 조건을 충족하는 것이 없기 때문에), 이로 인해 high0이 되고 priority_high0으로 기록됩니다. 이것이 score_to_hide_post에 전달되어 값을 붕괴시킵니다.


영향

  • score_to_hide_post0이 되면, 게시물이 잘못 숨겨진 것으로 간주되거나 합리적인 숨김 기준선에 의존하는 로직이 깨질 수 있습니다.
  • 이는 많은 reviewable이 존재하지만 각각 단일 플래그/리뷰어만 가진 사이트에서 발생하며, 이는 중소규모 커뮤니티에서 드문 일이 아닙니다.

권장 수정 사항 (옵션)

  1. 기록하기 전에 백분위수 쿼리가 충분한 행을 반환하도록 보장
  • 백분위수 쿼리를 실행한 후, 백분위수 값이 0인지 및 서브쿼리가 행을 반환했는지를 확인합니다.
    행이 반환되지 않았다면, 기존 priority_high덮어쓰지 말고 대신 기록을 건너뛰거나 이전 값을 유지하거나 구성된 기본값으로 폴백합니다.
  • 이것이 가장 안전하고 침습적이지 않은 접근 방식입니다.
  1. target_count를 고려하여 작업 트리거 조정
  • 작업 사전 확인을 수정하여, HAVING COUNT(*) >= :target_count를 충족하는 reviewable의 수가 최소 min_reviewables 이상일 때만 실행되도록 합니다.
    즉, COUNT(*) >= target_count를 만족하는 id별 그룹화된 reviewable을 카운트하고, 해당 수가 min_reviewables 이상일 때만 진행합니다.
  1. 관리자가 score_to_hide_post 또는 priority_high를 수동으로 설정할 수 있도록 허용
  • 관리자 인터페이스에서 score_to_hide_post 또는 priority_high를 직접 입력하거나 조정할 수 있는 옵션을 제공합니다.
  • 이렇게 하면 백분위수 쿼리가 예상치 못한 결과를 생성하더라도(예: 샘플이 너무 적을 경우), 시스템이 관리자가 지정한 합리적인 기준선을 사용하여 자동 계산으로 인한 오류를 방지할 수 있습니다.