From: Tom Hughes Date: Mon, 28 Nov 2016 20:31:04 +0000 (+0000) Subject: Clone objects before saving in case of a retry X-Git-Tag: live~4567 X-Git-Url: https://git.openstreetmap.org./rails.git/commitdiff_plain/e5834016fd30a975d162478469d030fc168d98fe Clone objects before saving in case of a retry If a deadlock occurs then the transaction will be retried so we need to make sure that the object will still be dirty so that it will be saved again during the retry but that the version won't be incremented a second time. --- diff --git a/app/models/node.rb b/app/models/node.rb index 2a64259c1..f8559dca7 100644 --- a/app/models/node.rb +++ b/app/models/node.rb @@ -232,10 +232,14 @@ class Node < ActiveRecord::Base def save_with_history! t = Time.now.getutc + + self.version += 1 + self.timestamp = t + Node.transaction do - self.version += 1 - self.timestamp = t - save! + # clone the object before saving it so that the original is + # still marked as dirty if we retry the transaction + clone.save! # Create a NodeTag tags = self.tags diff --git a/app/models/relation.rb b/app/models/relation.rb index e5e4ec894..b78c95ce4 100644 --- a/app/models/relation.rb +++ b/app/models/relation.rb @@ -281,15 +281,19 @@ class Relation < ActiveRecord::Base private def save_with_history! + t = Time.now.getutc + + self.version += 1 + self.timestamp = t + Relation.transaction do # have to be a little bit clever here - to detect if any tags # changed then we have to monitor their before and after state. tags_changed = false - t = Time.now.getutc - self.version += 1 - self.timestamp = t - save! + # clone the object before saving it so that the original is + # still marked as dirty if we retry the transaction + clone.save! tags = self.tags.clone relation_tags.each do |old_tag| diff --git a/app/models/way.rb b/app/models/way.rb index 98c4902f9..9877b8bb8 100644 --- a/app/models/way.rb +++ b/app/models/way.rb @@ -255,6 +255,9 @@ class Way < ActiveRecord::Base def save_with_history! t = Time.now.getutc + self.version += 1 + self.timestamp = t + # update the bounding box, note that this has to be done both before # and after the save, so that nodes from both versions are included in the # bbox. we use a copy of the changeset so that it isn't reloaded @@ -263,9 +266,9 @@ class Way < ActiveRecord::Base cs.update_bbox!(bbox) unless nodes.empty? Way.transaction do - self.version += 1 - self.timestamp = t - save! + # clone the object before saving it so that the original is + # still marked as dirty if we retry the transaction + clone.save! tags = self.tags WayTag.delete_all(:way_id => id)