mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 15:06:26 +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
|
||||
SQL
|
||||
|
||||
# update up to BATCH_SIZE records that are out of date based on age
|
||||
# we need an extra index for this
|
||||
DB.exec(<<~SQL, args)
|
||||
# we may end up update 2x batch size, this is ok
|
||||
# we need to update 1 batch of high scoring topics
|
||||
# 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
|
||||
SET score = (
|
||||
CASE WHEN topics.created_at > :recent_cutoff
|
||||
|
@ -121,11 +138,11 @@ class TopicHotScore < ActiveRecord::Base
|
|||
|
||||
FROM topics
|
||||
WHERE topics.id IN (
|
||||
SELECT topic_id FROM topic_hot_scores
|
||||
ORDER BY score DESC, recent_first_bumped_at DESC NULLS LAST
|
||||
LIMIT :max
|
||||
SELECT topic_id FROM topic_ids
|
||||
) AND ths.topic_id = topics.id
|
||||
SQL
|
||||
|
||||
DB.exec(sql, args)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -6,6 +6,28 @@ RSpec.describe TopicHotScore do
|
|||
fab!(:user2) { 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
|
||||
freeze_time
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user