FIX: under rare conditions saving a new draft could error temporarily
Under rare conditions due to bad HTTP timing and so on a draft could be set at the exact same time from 2 unicorn workers. When this happened and all the stars aligned, one of the sets would win and the other would raise an error. This transparently handles the situation without adding any cost to the draft system. The alternative is to add a distributed mutex, tricky DB transaction or handle the error in the controller. However this seems like a reasonable way to work around a pretty big edge case.
This commit is contained in:
parent
c031434b86
commit
34ede90927
|
@ -7,7 +7,7 @@ class Draft < ActiveRecord::Base
|
|||
|
||||
class OutOfSequence < StandardError; end
|
||||
|
||||
def self.set(user, key, sequence, data, owner = nil)
|
||||
def self.set(user, key, sequence, data, owner = nil, retry_not_unique: true)
|
||||
if SiteSetting.backup_drafts_to_pm_length > 0 && SiteSetting.backup_drafts_to_pm_length < data.length
|
||||
backup_draft(user, key, sequence, data)
|
||||
end
|
||||
|
@ -65,13 +65,24 @@ class Draft < ActiveRecord::Base
|
|||
elsif sequence != current_sequence
|
||||
raise Draft::OutOfSequence
|
||||
else
|
||||
Draft.create!(
|
||||
user_id: user.id,
|
||||
draft_key: key,
|
||||
data: data,
|
||||
sequence: sequence,
|
||||
owner: owner
|
||||
)
|
||||
begin
|
||||
Draft.create!(
|
||||
user_id: user.id,
|
||||
draft_key: key,
|
||||
data: data,
|
||||
sequence: sequence,
|
||||
owner: owner
|
||||
)
|
||||
rescue ActiveRecord::RecordNotUnique => e
|
||||
# we need this to be fast and with minimal locking, in some cases we can have a race condition
|
||||
# around 2 controller actions calling for draft creation at the exact same time
|
||||
# to avoid complex locking and a distributed mutex, since this is so rare, simply add a single retry
|
||||
if retry_not_unique
|
||||
set(user, key, sequence, data, owenr, retry_not_unique: false)
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sequence
|
||||
|
|
Loading…
Reference in New Issue