17152: Moves conditional preserve_version disabling to collection's controller.
[arvados.git] / services / api / app / models / collection.rb
index c7d5a93b5377c58f3ed556444048c8962bb24dcf..c2c60ec70e0202038151206eb1ace452fe1d1268 100644 (file)
@@ -37,6 +37,8 @@ class Collection < ArvadosModel
   validate :protected_managed_properties_updates, on: :update
   after_validation :set_file_count_and_total_size
   before_save :set_file_names
+  before_update :preserve_version_exclusive_updates_leave_modified_at_alone,
+    if: Proc.new { |col| col.changes.keys.sort == ['modified_at', 'updated_at', 'preserve_version'].sort }
   around_update :manage_versioning, unless: :is_past_version?
 
   api_accessible :user, extend: :common do |t|
@@ -62,6 +64,8 @@ class Collection < ArvadosModel
     t.add :file_size_total
   end
 
+  UNLOGGED_CHANGES = ['preserve_version', 'updated_at']
+
   after_initialize do
     @signatures_checked = false
     @computed_pdh_for_manifest_text = false
@@ -259,20 +263,22 @@ class Collection < ArvadosModel
     should_preserve_version = should_preserve_version? # Time sensitive, cache value
     return(yield) unless (should_preserve_version || syncable_updates.any?)
 
-    # Put aside the changes because with_lock requires an explicit record reload
+    # Put aside the changes because with_lock does a record reload
     changes = self.changes
     snapshot = nil
-    reload.with_lock do
+    restore_attributes
+    with_lock do
       # Copy the original state to save it as old version
       if should_preserve_version
         snapshot = self.dup
         snapshot.uuid = nil # Reset UUID so it's created as a new record
         snapshot.created_at = self.created_at
+        snapshot.modified_at = self.modified_at_was
       end
 
       # Restore requested changes on the current version
       changes.keys.each do |attr|
-        if attr == 'preserve_version' && changes[attr].last == false
+        if attr == 'preserve_version' && changes[attr].last == false && !should_preserve_version
           next # Ignore false assignment, once true it'll be true until next version
         end
         self.attributes = {attr => changes[attr].last}
@@ -284,7 +290,6 @@ class Collection < ArvadosModel
 
       if should_preserve_version
         self.version += 1
-        self.preserve_version = false
       end
 
       yield
@@ -293,14 +298,20 @@ class Collection < ArvadosModel
       if snapshot
         snapshot.attributes = self.syncable_updates
         leave_modified_by_user_alone do
-          act_as_system_user do
-            snapshot.save
+          leave_modified_at_alone do
+            act_as_system_user do
+              snapshot.save
+            end
           end
         end
       end
     end
   end
 
+  def preserve_version_exclusive_updates_leave_modified_at_alone
+    self.modified_at = self.modified_at_was
+  end
+
   def syncable_updates
     updates = {}
     if self.changes.any?
@@ -355,6 +366,7 @@ class Collection < ArvadosModel
 
     idle_threshold = Rails.configuration.Collections.PreserveVersionIfIdle
     if !self.preserve_version_was &&
+      !self.preserve_version &&
       (idle_threshold < 0 ||
         (idle_threshold > 0 && self.modified_at_was > db_current_time-idle_threshold.seconds))
       return false
@@ -738,4 +750,8 @@ class Collection < ArvadosModel
     self.current_version_uuid ||= self.uuid
     true
   end
+
+  def log_update
+    super unless (saved_changes.keys - UNLOGGED_CHANGES).empty?
+  end
 end