FIX: eliminate race condition creating posts

FIX: correct message bus posting
This commit is contained in:
Sam 2014-07-30 14:04:27 +10:00
parent e7e70d14da
commit 9147af1d62
2 changed files with 24 additions and 4 deletions

View File

@ -1,6 +1,10 @@
# Cross-process locking using Redis.
class DistributedMutex
def self.synchronize(key, redis=nil, &blk)
self.new(key, redis).synchronize(&blk)
end
def initialize(key, redis=nil)
@key = key
@redis = redis || $redis

View File

@ -3,6 +3,7 @@
require_dependency 'rate_limiter'
require_dependency 'topic_creator'
require_dependency 'post_jobs_enqueuer'
require_dependency 'distributed_mutex'
class PostCreator
@ -54,7 +55,7 @@ class PostCreator
@topic = nil
@post = nil
Post.transaction do
transaction do
setup_topic
setup_post
rollback_if_host_spam_detected
@ -66,21 +67,24 @@ class PostCreator
update_user_counts
create_embedded_topic
publish
ensure_in_allowed_users if guardian.is_staff?
@post.advance_draft_sequence
@post.save_reply_relationships
end
if @post
if @post && @post.errors.empty?
publish
PostAlerter.post_created(@post) unless @opts[:import_mode]
handle_spam unless @opts[:import_mode]
track_latest_on_category
enqueue_jobs
BadgeGranter.queue_badge_grant(Badge::Trigger::PostRevision, post: @post)
end
if @post && (@post.errors.present? || @spam)
handle_spam unless @opts[:import_mode]
end
@post
end
@ -111,6 +115,18 @@ class PostCreator
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.
# This is used by the wp-discourse plugin to associate a remote post with a
# discourse post.