mirror of
https://github.com/discourse/discourse.git
synced 2025-04-26 09:14:28 +08:00
FIX: hot not adding recently bumped topics (#25619)
When we insert into the hot set we add things with a score of 0 This means that if hot has more than batch size items in it with a score, then the 0s don't get an initial score This corrects the situation by always ensuring we re-score: 1. batch size high scoring topics 2. (new) batch size recently bumped topics * Update spec/models/topic_hot_scores_spec.rb Co-authored-by: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com> --------- Co-authored-by: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com>
This commit is contained in:
parent
c9b9463ee3
commit
c8410537c1
@ -102,9 +102,26 @@ class TopicHotScore < ActiveRecord::Base
|
|||||||
WHERE thsOrig.topic_id = ths.topic_id
|
WHERE thsOrig.topic_id = ths.topic_id
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
# update up to BATCH_SIZE records that are out of date based on age
|
# we may end up update 2x batch size, this is ok
|
||||||
# we need an extra index for this
|
# we need to update 1 batch of high scoring topics
|
||||||
DB.exec(<<~SQL, args)
|
# we need to update a second batch of recently bumped topics
|
||||||
|
sql = <<~SQL
|
||||||
|
WITH topic_ids AS (
|
||||||
|
SELECT topic_id FROM (
|
||||||
|
SELECT th3.topic_id FROM topic_hot_scores th3
|
||||||
|
JOIN topics t3 on t3.id = th3.topic_id
|
||||||
|
ORDER BY t3.bumped_at DESC
|
||||||
|
LIMIT :max
|
||||||
|
) Y
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT topic_id FROM (
|
||||||
|
SELECT th2.topic_id FROM topic_hot_scores th2
|
||||||
|
ORDER BY th2.score DESC, th2.recent_first_bumped_at DESC NULLS LAST
|
||||||
|
LIMIT :max
|
||||||
|
) X
|
||||||
|
)
|
||||||
UPDATE topic_hot_scores ths
|
UPDATE topic_hot_scores ths
|
||||||
SET score = (
|
SET score = (
|
||||||
CASE WHEN topics.created_at > :recent_cutoff
|
CASE WHEN topics.created_at > :recent_cutoff
|
||||||
@ -121,11 +138,11 @@ class TopicHotScore < ActiveRecord::Base
|
|||||||
|
|
||||||
FROM topics
|
FROM topics
|
||||||
WHERE topics.id IN (
|
WHERE topics.id IN (
|
||||||
SELECT topic_id FROM topic_hot_scores
|
SELECT topic_id FROM topic_ids
|
||||||
ORDER BY score DESC, recent_first_bumped_at DESC NULLS LAST
|
|
||||||
LIMIT :max
|
|
||||||
) AND ths.topic_id = topics.id
|
) AND ths.topic_id = topics.id
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
|
DB.exec(sql, args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -6,6 +6,28 @@ RSpec.describe TopicHotScore do
|
|||||||
fab!(:user2) { Fabricate(:user) }
|
fab!(:user2) { Fabricate(:user) }
|
||||||
fab!(:user3) { Fabricate(:user) }
|
fab!(:user3) { Fabricate(:user) }
|
||||||
|
|
||||||
|
it "also always updates based on recent activity" do
|
||||||
|
freeze_time
|
||||||
|
|
||||||
|
# this will come in with a score
|
||||||
|
topic = Fabricate(:topic, created_at: 1.hour.ago, bumped_at: 2.minutes.ago)
|
||||||
|
post = Fabricate(:post, topic: topic, created_at: 2.minute.ago)
|
||||||
|
PostActionCreator.like(user, post)
|
||||||
|
|
||||||
|
TopicHotScore.update_scores
|
||||||
|
|
||||||
|
# this will come in in the batch in score 0
|
||||||
|
topic = Fabricate(:topic, created_at: 1.minute.ago, bumped_at: 1.minute.ago)
|
||||||
|
post = Fabricate(:post, topic: topic, created_at: 1.minute.ago)
|
||||||
|
PostActionCreator.like(user, post)
|
||||||
|
|
||||||
|
# batch size is 1 so if we do not do something special we only update
|
||||||
|
# the high score topic and skip new
|
||||||
|
TopicHotScore.update_scores(1)
|
||||||
|
|
||||||
|
expect(TopicHotScore.find_by(topic_id: topic.id).score).to be_within(0.001).of(0.861)
|
||||||
|
end
|
||||||
|
|
||||||
it "can correctly update like counts and post counts and account for activity" do
|
it "can correctly update like counts and post counts and account for activity" do
|
||||||
freeze_time
|
freeze_time
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user