摘要
score_to_hide_post 可以被驱动到 0,因为后台作业 Jobs::ReviewablePriorities 在百分位数查询返回空行时,会将 priority_#{priorities[:high]} 写入为 0。该作业在 reviewable_count >= 15 时触发,但百分位数计算仅包括满足 HAVING COUNT(*) >= :target_count(其中 target_count 通常为 2)的 reviewables。如果大多数 reviewables 只有一个标记,百分位数子查询将不返回任何内容 → high 变为 0 → score_to_hide_post = ((high * ratio) * scale).truncate(2) 计算结果为 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_reviewables 是 15。
- 作业使用 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。
根本原因
两个独立的阈值共同造成了一个差距:
- 作业在存在至少
min_reviewables(15)个高于min_priority_threshold的 reviewables 时触发——这是一个粗略的计数,忽略了:target_count要求。 - 但产生
high的百分位数计算仅包括满足COUNT(*) >= :target_count(即至少有2个 reviewable_scores)的 reviewables。如果许多 reviewables 每个只有一个标记,子查询将不返回任何行,百分位数将返回默认值0.0。
因此,作业可以运行(因为粗略计数有 >= 15 个 reviewables),但百分位数聚合没有符合条件的行(因为没有满足 HAVING 的),导致 high 为 0,然后 priority_high 被写入为 0。这会影响 score_to_hide_post 并使其失效。
影响
score_to_hide_post变为0,这可能错误地导致帖子被视为隐藏或破坏依赖于合理隐藏阈值的逻辑。- 这发生在许多 reviewables 但每个只有一个标记/审阅者的情况下,这在小型/中等社区中并不少见。
建议的修复方法(选项)
- 在写入之前确保百分位数查询返回足够的行
- 运行百分位数查询后,检查百分位数是否为
0以及子查询是否返回了任何行。 - 如果未返回行,请不要覆盖现有的
priority_high;而是跳过写入,保留先前的值,或回退到配置的默认值。 - 这是最安全、侵入性最小的方法。
- 调整作业触发器以考虑
target_count
- 修改作业预检查,使其仅在满足
HAVING COUNT(*) >= :target_count的 reviewables 数量至少为min_reviewables时运行。
换句话说,按id分组计算满足COUNT(*) >= target_count的 reviewables,并且仅当该计数 ≥min_reviewables时才继续。
- 允许管理员手动设置
score_to_hide_post或priority_high
- 在管理员界面中提供一个选项,用于直接输入或调整
score_to_hide_post或priority_high。 - 这样,即使百分位数查询产生意外结果(例如,由于样本太少),系统也可以使用管理员指定的合理阈值,从而防止自动计算导致的错误。