mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 08:57:10 -06:00
FIX: keep topic.word_count in sync (#27065)
Whenever one creates, updates, or deletes a post, we should keep the `topic.word_count` counter in sync. Context - https://meta.discourse.org/t/-/308062
This commit is contained in:
parent
57eff8b760
commit
b908abe35a
@ -855,14 +855,22 @@ class Topic < ActiveRecord::Base
|
|||||||
FROM posts
|
FROM posts
|
||||||
WHERE deleted_at IS NULL AND post_type <> 4
|
WHERE deleted_at IS NULL AND post_type <> 4
|
||||||
GROUP BY topic_id
|
GROUP BY topic_id
|
||||||
|
),
|
||||||
|
Z as (
|
||||||
|
SELECT topic_id,
|
||||||
|
SUM(COALESCE(posts.word_count, 0)) word_count
|
||||||
|
FROM posts
|
||||||
|
WHERE deleted_at IS NULL AND post_type <> 4
|
||||||
|
GROUP BY topic_id
|
||||||
)
|
)
|
||||||
UPDATE topics
|
UPDATE topics
|
||||||
SET
|
SET
|
||||||
highest_staff_post_number = X.highest_post_number,
|
highest_staff_post_number = X.highest_post_number,
|
||||||
highest_post_number = Y.highest_post_number,
|
highest_post_number = Y.highest_post_number,
|
||||||
last_posted_at = Y.last_posted_at,
|
last_posted_at = Y.last_posted_at,
|
||||||
posts_count = Y.posts_count
|
posts_count = Y.posts_count,
|
||||||
FROM X, Y
|
word_count = Z.word_count
|
||||||
|
FROM X, Y, Z
|
||||||
WHERE
|
WHERE
|
||||||
topics.archetype <> 'private_message' AND
|
topics.archetype <> 'private_message' AND
|
||||||
X.topic_id = topics.id AND
|
X.topic_id = topics.id AND
|
||||||
@ -870,7 +878,8 @@ class Topic < ActiveRecord::Base
|
|||||||
topics.highest_staff_post_number <> X.highest_post_number OR
|
topics.highest_staff_post_number <> X.highest_post_number OR
|
||||||
topics.highest_post_number <> Y.highest_post_number OR
|
topics.highest_post_number <> Y.highest_post_number OR
|
||||||
topics.last_posted_at <> Y.last_posted_at OR
|
topics.last_posted_at <> Y.last_posted_at OR
|
||||||
topics.posts_count <> Y.posts_count
|
topics.posts_count <> Y.posts_count OR
|
||||||
|
topics.word_count <> Z.word_count
|
||||||
)
|
)
|
||||||
SQL
|
SQL
|
||||||
|
|
||||||
@ -891,14 +900,22 @@ class Topic < ActiveRecord::Base
|
|||||||
FROM posts
|
FROM posts
|
||||||
WHERE deleted_at IS NULL AND post_type <> 3 AND post_type <> 4
|
WHERE deleted_at IS NULL AND post_type <> 3 AND post_type <> 4
|
||||||
GROUP BY topic_id
|
GROUP BY topic_id
|
||||||
|
),
|
||||||
|
Z as (
|
||||||
|
SELECT topic_id,
|
||||||
|
SUM(COALESCE(posts.word_count, 0)) word_count
|
||||||
|
FROM posts
|
||||||
|
WHERE deleted_at IS NULL AND post_type <> 3 AND post_type <> 4
|
||||||
|
GROUP BY topic_id
|
||||||
)
|
)
|
||||||
UPDATE topics
|
UPDATE topics
|
||||||
SET
|
SET
|
||||||
highest_staff_post_number = X.highest_post_number,
|
highest_staff_post_number = X.highest_post_number,
|
||||||
highest_post_number = Y.highest_post_number,
|
highest_post_number = Y.highest_post_number,
|
||||||
last_posted_at = Y.last_posted_at,
|
last_posted_at = Y.last_posted_at,
|
||||||
posts_count = Y.posts_count
|
posts_count = Y.posts_count,
|
||||||
FROM X, Y
|
word_count = Z.word_count
|
||||||
|
FROM X, Y, Z
|
||||||
WHERE
|
WHERE
|
||||||
topics.archetype = 'private_message' AND
|
topics.archetype = 'private_message' AND
|
||||||
X.topic_id = topics.id AND
|
X.topic_id = topics.id AND
|
||||||
@ -906,7 +923,8 @@ class Topic < ActiveRecord::Base
|
|||||||
topics.highest_staff_post_number <> X.highest_post_number OR
|
topics.highest_staff_post_number <> X.highest_post_number OR
|
||||||
topics.highest_post_number <> Y.highest_post_number OR
|
topics.highest_post_number <> Y.highest_post_number OR
|
||||||
topics.last_posted_at <> Y.last_posted_at OR
|
topics.last_posted_at <> Y.last_posted_at OR
|
||||||
topics.posts_count <> Y.posts_count
|
topics.posts_count <> Y.posts_count OR
|
||||||
|
topics.word_count <> Z.word_count
|
||||||
)
|
)
|
||||||
SQL
|
SQL
|
||||||
end
|
end
|
||||||
@ -941,6 +959,13 @@ class Topic < ActiveRecord::Base
|
|||||||
post_type <> 4
|
post_type <> 4
|
||||||
#{post_type}
|
#{post_type}
|
||||||
),
|
),
|
||||||
|
word_count = (
|
||||||
|
SELECT SUM(COALESCE(posts.word_count, 0)) FROM posts
|
||||||
|
WHERE topic_id = :topic_id AND
|
||||||
|
deleted_at IS NULL AND
|
||||||
|
post_type <> 4
|
||||||
|
#{post_type}
|
||||||
|
),
|
||||||
last_posted_at = (
|
last_posted_at = (
|
||||||
SELECT MAX(created_at) FROM posts
|
SELECT MAX(created_at) FROM posts
|
||||||
WHERE topic_id = :topic_id AND
|
WHERE topic_id = :topic_id AND
|
||||||
|
@ -287,6 +287,9 @@ class PostRevisor
|
|||||||
advance_draft_sequence if !opts[:keep_existing_draft]
|
advance_draft_sequence if !opts[:keep_existing_draft]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# bail out if the post or topic failed to save
|
||||||
|
return false if !successfully_saved_post_and_topic
|
||||||
|
|
||||||
# Lock the post by default if the appropriate setting is true
|
# Lock the post by default if the appropriate setting is true
|
||||||
if (
|
if (
|
||||||
SiteSetting.staff_edit_locks_post? && !@post.wiki? && @fields.has_key?("raw") &&
|
SiteSetting.staff_edit_locks_post? && !@post.wiki? && @fields.has_key?("raw") &&
|
||||||
@ -312,16 +315,15 @@ class PostRevisor
|
|||||||
# it can fire events in sidekiq before the post is done saving
|
# it can fire events in sidekiq before the post is done saving
|
||||||
# leading to corrupt state
|
# leading to corrupt state
|
||||||
QuotedPost.extract_from(@post)
|
QuotedPost.extract_from(@post)
|
||||||
|
TopicLink.extract_from(@post)
|
||||||
|
|
||||||
|
Topic.reset_highest(@topic.id)
|
||||||
|
|
||||||
post_process_post
|
post_process_post
|
||||||
|
|
||||||
update_topic_word_counts
|
|
||||||
alert_users
|
alert_users
|
||||||
publish_changes
|
publish_changes
|
||||||
grant_badge
|
grant_badge
|
||||||
|
|
||||||
TopicLink.extract_from(@post)
|
|
||||||
|
|
||||||
ReviewablePost.queue_for_review_if_possible(@post, @editor) if should_create_new_version?
|
ReviewablePost.queue_for_review_if_possible(@post, @editor) if should_create_new_version?
|
||||||
|
|
||||||
successfully_saved_post_and_topic
|
successfully_saved_post_and_topic
|
||||||
@ -714,19 +716,6 @@ class PostRevisor
|
|||||||
DiscourseEvent.trigger(:post_edited, @post, self.topic_changed?, self)
|
DiscourseEvent.trigger(:post_edited, @post, self.topic_changed?, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_topic_word_counts
|
|
||||||
DB.exec(
|
|
||||||
"UPDATE topics
|
|
||||||
SET word_count = (
|
|
||||||
SELECT SUM(COALESCE(posts.word_count, 0))
|
|
||||||
FROM posts
|
|
||||||
WHERE posts.topic_id = :topic_id
|
|
||||||
)
|
|
||||||
WHERE topics.id = :topic_id",
|
|
||||||
topic_id: @topic.id,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def alert_users
|
def alert_users
|
||||||
return if @editor.id == Discourse::SYSTEM_USER_ID
|
return if @editor.id == Discourse::SYSTEM_USER_ID
|
||||||
Jobs.enqueue(:post_alert, post_id: @post.id)
|
Jobs.enqueue(:post_alert, post_id: @post.id)
|
||||||
|
@ -735,6 +735,7 @@ RSpec.describe PostCreator do
|
|||||||
highest_staff_post_number: 0,
|
highest_staff_post_number: 0,
|
||||||
highest_post_number: 0,
|
highest_post_number: 0,
|
||||||
posts_count: 0,
|
posts_count: 0,
|
||||||
|
word_count: 0,
|
||||||
last_posted_at: 1.year.ago,
|
last_posted_at: 1.year.ago,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -743,6 +744,7 @@ RSpec.describe PostCreator do
|
|||||||
topic.reload
|
topic.reload
|
||||||
expect(topic.highest_post_number).to eq(1)
|
expect(topic.highest_post_number).to eq(1)
|
||||||
expect(topic.posts_count).to eq(1)
|
expect(topic.posts_count).to eq(1)
|
||||||
|
expect(topic.word_count).to eq(5)
|
||||||
expect(topic.last_posted_at).to eq_time(first.created_at)
|
expect(topic.last_posted_at).to eq_time(first.created_at)
|
||||||
expect(topic.highest_staff_post_number).to eq(3)
|
expect(topic.highest_staff_post_number).to eq(3)
|
||||||
end
|
end
|
||||||
@ -1187,10 +1189,10 @@ RSpec.describe PostCreator do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "does not increase posts count for small actions" do
|
it "does not increase posts/words count for small actions" do
|
||||||
topic = Fabricate(:private_message_topic, user: Fabricate(:user, refresh_auto_groups: true))
|
topic = Fabricate(:private_message_topic, user: Fabricate(:user, refresh_auto_groups: true))
|
||||||
|
|
||||||
Fabricate(:post, topic: topic)
|
p1 = Fabricate(:post, topic: topic)
|
||||||
|
|
||||||
1.upto(3) do |i|
|
1.upto(3) do |i|
|
||||||
user = Fabricate(:user)
|
user = Fabricate(:user)
|
||||||
@ -1200,13 +1202,19 @@ RSpec.describe PostCreator do
|
|||||||
expect(topic.posts.where(post_type: Post.types[:small_action]).count).to eq(i)
|
expect(topic.posts.where(post_type: Post.types[:small_action]).count).to eq(i)
|
||||||
end
|
end
|
||||||
|
|
||||||
Fabricate(:post, topic: topic)
|
expect(topic.word_count).to eq(0)
|
||||||
Topic.reset_highest(topic.id)
|
|
||||||
expect(topic.reload.posts_count).to eq(2)
|
|
||||||
|
|
||||||
Fabricate(:post, topic: topic)
|
p2 = Fabricate(:post, topic: topic)
|
||||||
|
Topic.reset_highest(topic.id)
|
||||||
|
topic.reload
|
||||||
|
expect(topic.posts_count).to eq(2)
|
||||||
|
expect(topic.word_count).to eq([p1, p2].sum(&:word_count))
|
||||||
|
|
||||||
|
p3 = Fabricate(:post, topic: topic)
|
||||||
Topic.reset_all_highest!
|
Topic.reset_all_highest!
|
||||||
expect(topic.reload.posts_count).to eq(3)
|
topic.reload
|
||||||
|
expect(topic.posts_count).to eq(3)
|
||||||
|
expect(topic.word_count).to eq([p1, p2, p3].sum(&:word_count))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2874,6 +2874,7 @@ RSpec.describe Topic do
|
|||||||
topic.reload
|
topic.reload
|
||||||
|
|
||||||
expect(topic.posts_count).to eq(1)
|
expect(topic.posts_count).to eq(1)
|
||||||
|
expect(topic.word_count).to eq(post1.word_count)
|
||||||
expect(topic.highest_post_number).to eq(post1.post_number)
|
expect(topic.highest_post_number).to eq(post1.post_number)
|
||||||
expect(topic.highest_staff_post_number).to eq(post2.post_number)
|
expect(topic.highest_staff_post_number).to eq(post2.post_number)
|
||||||
expect(topic.last_posted_at).to eq_time(post1.created_at)
|
expect(topic.last_posted_at).to eq_time(post1.created_at)
|
||||||
|
Loading…
Reference in New Issue
Block a user