summaryrefslogtreecommitdiff
path: root/app/models/gs_cluster_sync_log_entry.rb
blob: 51e3b052bed2bc93d12eebac3935cc1a0fcea68e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
class GsClusterSyncLogEntry < ActiveRecord::Base
  attr_accessible :gs_node_id, :class_name, :action, :content, :status, :history, 
                  :homebase_ip_address, :waiting_to_be_synced, :association_method,
                  :association_uuid

  validates :class_name,
            :presence => true

  validates :action,
            :presence => true

  validates :content,
            :presence => true

  after_create :apply_to_local_database

  def apply_to_local_database
    if self.homebase_ip_address != GsParameter.get('HOMEBASE_IP_ADDRESS')
      if self.class_name.constantize.new.attribute_names.include?('is_native')
        case self.action
        when 'create'
          new_local_copy = self.class_name.constantize.new(
                           JSON(self.content).
                           delete_if{|key, value| ['id','updated_at','created_at'].
                           include?(key) }, 
                           :without_protection => true)
          new_local_copy.is_native = false
          find_and_connect_to_an_association(new_local_copy)
          if new_local_copy.save(:validate => false)
            logger.info "Created local copy of #{self.class_name} with the ID #{new_local_copy.id}. #{new_local_copy.to_s}"
          else
            logger.error "Couldn't create a local copy of #{self.class_name} with the ID #{new_local_copy.id}. #{new_local_copy.errors.to_yaml}"
          end

        when 'update'
          local_copy = find_local_copy
          if local_copy
            # Only update an object if the update it self is newer than the local object.
            #
            if local_copy.updated_at < JSON(self.content)['updated_at'].to_time
              local_copy.update_attributes(JSON(self.content).delete_if{|key, value| ['id','updated_at','created_at'].include?(key) }, :without_protection => true)
              find_and_connect_to_an_association(local_copy)
              if local_copy.save(:validate => false)
                logger.info "Updated local copy of #{self.class_name} with the ID #{local_copy.id}. #{local_copy.to_s}"
              else
                logger.error "Couldn't update local copy of #{self.class_name} with the ID #{local_copy.id}. #{local_copy.errors.to_yaml}"
              end
            else
              logger.error "Didn't update local copy of #{self.class_name} with the ID #{local_copy.id} because of a race condition (the local version was newer than the update). Please check GsClusterSyncLogEntry ID #{self.id}."
            end
          else
            logger.error "Couldn't find local copy of #{self.class_name}. #{self.content}"
          end 

        when 'destroy'
          local_copy = find_local_copy
          if local_copy
            local_copy.destroy
            logger.info "Destroyed local copy of #{self.class_name} with the ID #{local_copy.id}. #{local_copy.to_s}"
          else
            logger.error "Couldn't find local copy of #{self.class_name}. #{self.content}"
          end
        end
      else
        logger.error "The class #{self.class_name} doesn't offer the attribute is_native. Can't synchronize without."
      end
    end
  end

  def find_local_copy
    self.class_name.constantize.find_by_uuid(JSON(self.content)['uuid'])
  end

  # Connect to the association (e.g. User to a SipAccount)
  #
  def find_and_connect_to_an_association(local_copy)
    if !(self.association_method.blank? || self.association_uuid.blank?) && (self.association_method_changed? || self.association_uuid_changed?)
      name_of_the_association_type = local_copy.attribute_names.delete_if{|x| !x.include?('_type')}.first
      association = local_copy.send(name_of_the_association_type).constantize.where(:uuid => self.association_uuid).first
      if association
        local_copy.send "#{association_method}=", association
      end
    end
  end

  def populate_other_cluster_nodes
    if self.homebase_ip_address == GsParameter.get('HOMEBASE_IP_ADDRESS') && self.waiting_to_be_synced == true
      if GsNode.where(:push_updates_to => true).count > 0
        GsNode.where(:push_updates_to => true).each do |gs_node|
          RemoteGsNode::GsClusterSyncLogEntry.site = gs_node.site
          remote_enty = RemoteGsNode::GsClusterSyncLogEntry.create(self.attributes.delete_if{|key, value| ['id','updated_at','created_at'].include?(key) })
          self.update_attributes(:waiting_to_be_synced => false)
          self.save
        end
      end
    end
  end
  
end