mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-26 21:18:34 +08:00
When a group or user is renamed, `GroupMentionsUpdater` and `Jobs::UpdateUsername` update the post's raw/cooked content but skip `PostRevisor`, so `categories.description` (a denormalized copy of the first paragraph) is never refreshed. The Edit Category page and category banner keep showing the old name, while the actual topic shows the new one. Same issue with `Post#rebake!` (Rebuild HTML) and `ProcessPost`. Extract `Post#sync_category_description` as the single source of truth for deriving `categories.description` from a post's cooked HTML — both `PostRevisor` and the new `Post#sync_first_post_caches` now delegate to it. `sync_first_post_caches` also updates `topics.excerpt`, centralizing all first-post denormalized field updates. Call `sync_first_post_caches` from every code path that modifies post content outside PostRevisor: `GroupMentionsUpdater`, `UpdateUsername`, `ChangeDisplayName`, `ProcessPost`, and `Post#rebake!`. Skip the update when the description hasn't changed to avoid unnecessary writes. When it has changed, call `publish_category` and `Site.clear_cache` so connected clients see the update immediately (fixes a pre-existing flicker where the old description would briefly appear then get overwritten by stale cached site data). Also add a targeted query in `UpdateUsername` for category description posts authored by the system user, which were missed by the existing `user_actions`-based and self-mention queries. Ref - t/181445
78 lines
2.6 KiB
Ruby
Vendored
78 lines
2.6 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
require "image_sizer"
|
|
|
|
module Jobs
|
|
class ProcessPost < ::Jobs::Base
|
|
def execute(args)
|
|
DistributedMutex.synchronize("process_post_#{args[:post_id]}", validity: 10.minutes) do
|
|
post = Post.find_by(id: args[:post_id])
|
|
# two levels of deletion
|
|
return if post.blank? || post.topic.blank?
|
|
|
|
orig_cooked = post.cooked
|
|
recooked = nil
|
|
|
|
if args[:cook].present?
|
|
cooking_options = args[:cooking_options] || {}
|
|
cooking_options[:topic_id] = post.topic_id
|
|
recooked = post.cook(post.raw, cooking_options.symbolize_keys)
|
|
post.update_columns(
|
|
cooked: recooked,
|
|
baked_at: Time.zone.now,
|
|
baked_version: Post::BAKED_VERSION,
|
|
)
|
|
end
|
|
|
|
cp = CookedPostProcessor.new(post, args)
|
|
cp.post_process(new_post: args[:new_post])
|
|
|
|
# If we changed the document, save it
|
|
cooked = cp.html
|
|
|
|
if cooked != (recooked || orig_cooked)
|
|
if orig_cooked.present? && cooked.blank?
|
|
# TODO stop/restart the worker if needed, let's gather a few here first
|
|
Rails.logger.warn(
|
|
"Cooked post processor in FATAL state, bypassing. You need to urgently restart sidekiq\norig: #{orig_cooked}\nrecooked: #{recooked}\ncooked: #{cooked}\npost id: #{post.id}",
|
|
)
|
|
else
|
|
post.update_column(:cooked, cp.html)
|
|
post.sync_first_post_caches
|
|
extract_links(post)
|
|
post.publish_change_to_clients! :revised
|
|
end
|
|
end
|
|
|
|
enqueue_pull_hotlinked_images(post) unless args[:skip_pull_hotlinked_images]
|
|
|
|
if !post.user&.staff? && !post.user&.staged?
|
|
s = post.raw
|
|
s << " #{post.topic.title}" if post.post_number == 1
|
|
word_watcher = WordWatcher.new(s)
|
|
if !args[:bypass_bump] && word_watcher.should_flag?
|
|
words = word_watcher.word_matches_for_action?(:flag, all_matches: true)
|
|
PostActionCreator.create(
|
|
Discourse.system_user,
|
|
post,
|
|
:inappropriate,
|
|
reason: :watched_word,
|
|
context: words.join(","),
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
# onebox may have added some links, so extract them now
|
|
def extract_links(post)
|
|
TopicLink.extract_from(post)
|
|
QuotedPost.extract_from(post)
|
|
end
|
|
|
|
def enqueue_pull_hotlinked_images(post)
|
|
Jobs.cancel_scheduled_job(:pull_hotlinked_images, post_id: post.id)
|
|
Jobs.enqueue(:pull_hotlinked_images, post_id: post.id)
|
|
end
|
|
end
|
|
end
|