diff --git a/lib/email/sender.rb b/lib/email/sender.rb index 351cc2cc45d..f85760089eb 100644 --- a/lib/email/sender.rb +++ b/lib/email/sender.rb @@ -262,7 +262,8 @@ module Email post_id && header_value(Email::MessageBuilder::ALLOW_REPLY_BY_EMAIL_HEADER).present? - reply_key = PostReplyKey.find_or_create_by!( + # use safe variant here cause we tend to see concurrency issue + reply_key = PostReplyKey.find_or_create_by_safe!( post_id: post_id, user_id: user_id ).reply_key diff --git a/lib/freedom_patches/active_record_base.rb b/lib/freedom_patches/active_record_base.rb index a15d08fba33..7be646cde64 100644 --- a/lib/freedom_patches/active_record_base.rb +++ b/lib/freedom_patches/active_record_base.rb @@ -1,5 +1,17 @@ class ActiveRecord::Base + # Handle PG::UniqueViolation as well due to concurrency + # find_or_create does find_by(hash) || create!(hash) + # in some cases find will not find and multiple creates will be called + def self.find_or_create_by_safe!(hash) + begin + find_or_create_by!(hash) + rescue PG::UniqueViolation + # try again cause another transaction could have passed by now + find_or_create_by!(hash) + end + end + # Execute SQL manually def self.exec_sql(*args)