From 4d5ddb007262c4c85c5086040e9a09fc0d0f5374 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Lang Date: Thu, 13 Apr 2017 12:10:03 +0000 Subject: [PATCH] Prevent deadlocks by only locking the exact records we need to have locked (#25590). Patch by Jens Kraemer. git-svn-id: http://svn.redmine.org/redmine/trunk@16541 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- app/models/attachment.rb | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 26fe4a8b3..89b9f8a7c 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -417,27 +417,33 @@ class Attachment < ActiveRecord::Base reused = with_lock do if existing = Attachment - .lock .where(digest: self.digest, filesize: self.filesize) .where('id <> ? and disk_filename <> ?', self.id, self.disk_filename) .first + existing.with_lock do - original_diskfile = self.diskfile - existing_diskfile = existing.diskfile + original_diskfile = self.diskfile + existing_diskfile = existing.diskfile - if File.readable?(original_diskfile) && - File.readable?(existing_diskfile) && - FileUtils.identical?(original_diskfile, existing_diskfile) + if File.readable?(original_diskfile) && + File.readable?(existing_diskfile) && + FileUtils.identical?(original_diskfile, existing_diskfile) - self.update_columns disk_directory: existing.disk_directory, - disk_filename: existing.disk_filename + self.update_columns disk_directory: existing.disk_directory, + disk_filename: existing.disk_filename + end end end end if reused File.delete(original_diskfile) end + rescue ActiveRecord::StatementInvalid, ActiveRecord::RecordNotFound + # Catch and ignore lock errors. It is not critical if deduplication does + # not happen, therefore we do not retry. + # with_lock throws ActiveRecord::RecordNotFound if the record isnt there + # anymore, thats why this is caught and ignored as well. end -- 2.39.5