mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 16:01:38 +08:00
FIX: eliminate race condition creating posts
FIX: correct message bus posting
This commit is contained in:
parent
e7e70d14da
commit
9147af1d62
|
@ -1,6 +1,10 @@
|
||||||
# Cross-process locking using Redis.
|
# Cross-process locking using Redis.
|
||||||
class DistributedMutex
|
class DistributedMutex
|
||||||
|
|
||||||
|
def self.synchronize(key, redis=nil, &blk)
|
||||||
|
self.new(key, redis).synchronize(&blk)
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(key, redis=nil)
|
def initialize(key, redis=nil)
|
||||||
@key = key
|
@key = key
|
||||||
@redis = redis || $redis
|
@redis = redis || $redis
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
require_dependency 'rate_limiter'
|
require_dependency 'rate_limiter'
|
||||||
require_dependency 'topic_creator'
|
require_dependency 'topic_creator'
|
||||||
require_dependency 'post_jobs_enqueuer'
|
require_dependency 'post_jobs_enqueuer'
|
||||||
|
require_dependency 'distributed_mutex'
|
||||||
|
|
||||||
class PostCreator
|
class PostCreator
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ class PostCreator
|
||||||
@topic = nil
|
@topic = nil
|
||||||
@post = nil
|
@post = nil
|
||||||
|
|
||||||
Post.transaction do
|
transaction do
|
||||||
setup_topic
|
setup_topic
|
||||||
setup_post
|
setup_post
|
||||||
rollback_if_host_spam_detected
|
rollback_if_host_spam_detected
|
||||||
|
@ -66,21 +67,24 @@ class PostCreator
|
||||||
update_user_counts
|
update_user_counts
|
||||||
create_embedded_topic
|
create_embedded_topic
|
||||||
|
|
||||||
publish
|
|
||||||
ensure_in_allowed_users if guardian.is_staff?
|
ensure_in_allowed_users if guardian.is_staff?
|
||||||
@post.advance_draft_sequence
|
@post.advance_draft_sequence
|
||||||
@post.save_reply_relationships
|
@post.save_reply_relationships
|
||||||
end
|
end
|
||||||
|
|
||||||
if @post
|
if @post && @post.errors.empty?
|
||||||
|
publish
|
||||||
PostAlerter.post_created(@post) unless @opts[:import_mode]
|
PostAlerter.post_created(@post) unless @opts[:import_mode]
|
||||||
|
|
||||||
handle_spam unless @opts[:import_mode]
|
|
||||||
track_latest_on_category
|
track_latest_on_category
|
||||||
enqueue_jobs
|
enqueue_jobs
|
||||||
BadgeGranter.queue_badge_grant(Badge::Trigger::PostRevision, post: @post)
|
BadgeGranter.queue_badge_grant(Badge::Trigger::PostRevision, post: @post)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if @post && (@post.errors.present? || @spam)
|
||||||
|
handle_spam unless @opts[:import_mode]
|
||||||
|
end
|
||||||
|
|
||||||
@post
|
@post
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -111,6 +115,18 @@ class PostCreator
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
def transaction(&blk)
|
||||||
|
Post.transaction do
|
||||||
|
if new_topic?
|
||||||
|
blk.call
|
||||||
|
else
|
||||||
|
# we need to ensure post_number is monotonically increasing with no gaps
|
||||||
|
# so we serialize creation to avoid needing rollbacks
|
||||||
|
DistributedMutex.synchronize("topic_id_#{@opts[:topic_id]}", &blk)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# You can supply an `embed_url` for a post to set up the embedded relationship.
|
# You can supply an `embed_url` for a post to set up the embedded relationship.
|
||||||
# This is used by the wp-discourse plugin to associate a remote post with a
|
# This is used by the wp-discourse plugin to associate a remote post with a
|
||||||
# discourse post.
|
# discourse post.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user