Module: Switchman::ActiveRecord::Associations::Preloader::Association::LoaderRecords

Defined in:
lib/switchman/active_record/associations.rb

Overview

significant changes:

* associate shards with records
* look on all appropriate shards when loading records

Instance Method Summary collapse

Instance Method Details

#load_recordsObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/switchman/active_record/associations.rb', line 132

def load_records
  ret = []

  shards_with_keys = @sharded_keys_to_load.each_with_object({}) do |(key, shards), h|
    shards.each { |shard| (h[shard] ||= []) << key }
  end

  shards_with_keys.each do |shard, keys|
    Shard.lookup(shard).activate do
      scope_was = loader_query.scope
      begin
        loader_query.instance_variable_set(
          :@scope,
          loader_query.scope.shard(
            Shard.current(loader_query.scope.model.connection_class_for_self)
          )
        )
        ret += loader_query.load_records_for_keys(keys) do |record|
          loaders.each { |l| l.set_inverse(record) }
        end
      ensure
        loader_query.instance_variable_set(:@scope, scope_was)
      end
    end
  end

  ret
end

#populate_keys_to_load_and_already_loaded_recordsObject



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/switchman/active_record/associations.rb', line 102

def populate_keys_to_load_and_already_loaded_records
  @sharded_keys_to_load = {}

  loaders.each do |loader|
    multishard = loader.send(:reflection).options[:multishard]
    belongs_to = loader.send(:reflection).macro == :belongs_to
    loader.owners_by_key.each do |key, owners|
      if (loaded_owner = owners.find { |owner| loader.loaded?(owner) })
        already_loaded_records_by_key[key] = loader.target_for(loaded_owner)
      else
        shard_set = @sharded_keys_to_load[key] ||= Set.new
        owner_key_name = loader.send(:owner_key_name)
        owners.each do |owner|
          if multishard && owner.respond_to?(:associated_shards)
            shard_set.merge(owner.associated_shards.map(&:id))
          elsif belongs_to && owner.class.sharded_column?(owner_key_name)
            shard_set.add(Shard.shard_for(owner[owner_key_name], owner.shard).id)
          elsif belongs_to
            shard_set.add(Shard.current.id)
          else
            shard_set.add(owner.shard.id)
          end
        end
      end
    end
  end

  @sharded_keys_to_load.delete_if { |key, _shards| already_loaded_records_by_key.include?(key) }
end