Clone objects before saving in case of a retry
authorTom Hughes <tom@compton.nu>
Mon, 28 Nov 2016 20:31:04 +0000 (20:31 +0000)
committerTom Hughes <tom@compton.nu>
Mon, 28 Nov 2016 20:31:04 +0000 (20:31 +0000)
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.

app/models/node.rb
app/models/relation.rb
app/models/way.rb

index 2a64259c10c0832d16c4ec8e2008aa7e34985947..f8559dca75d74431153342f4c4c987281a5354e8 100644 (file)
@@ -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
index e5e4ec894c8d699ca781e69bc6564b376d8988c5..b78c95ce4ddc9f9c0c9f99b61a6a683ed627c67c 100644 (file)
@@ -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|
index 98c4902f9e693cd2396aaf84761df00c0c3a8d83..9877b8bb8ea2b8dcde7a26c3f93b599fb29f8904 100644 (file)
@@ -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)