switchman 3.1.3 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54ae135ce532aa5578592027f6ce46cf3aedecdf0a6fd097ae3597752f436bae
4
- data.tar.gz: 02d88f28e64e487c6841940a383afd92a56378ea7c2e4b1156252c0bcf0fa71f
3
+ metadata.gz: 20c8d947a29c73c09af7d1c880ef03aff2185c927d30954bb304b4592a7b4051
4
+ data.tar.gz: 5973474196cc2c8f2957932a65261998de24a6be3653cedeff374c1fe1fa925f
5
5
  SHA512:
6
- metadata.gz: 383075584faafb39abc64be4f6e77a99c4ca3dfd5acc1c57bae885ba71c8d13ce2cb0f89d9332fd8387f5100886a5a0ffbb6f6d53e382b0e54412aea6b72cf06
7
- data.tar.gz: 875421e2c515a671ed8503fd07b55d22e16f098ddde635b5530a3ab4801c9bebd06a5e4e75d7a547b1e84e5628288dac9aefc0c6f9a23cedad80b1f8389bb5de
6
+ metadata.gz: 10f59abb9c44a3b6e8ec3e87419862f5959ec8086117172d6fc044911c0efb3d96ec320fc04630e482200fbf99da4a7a8d7a291137bbf9ce019f1e7a54f5eeb0
7
+ data.tar.gz: 72fc286e4f143bf9d8344aa6e4a0405161e476b23eada4fd956f2657a1911c4e93acad649e76cb17e444821060085110d12c2cfe0a5f115bf9b7ddc598fb17ea
@@ -83,16 +83,62 @@ module Switchman
83
83
 
84
84
  module Preloader
85
85
  module Association
86
- module LoaderQuery
87
- def load_records_in_batch(loaders)
88
- # While in theory loading multiple associations that end up being effectively the same would be nice
89
- # it's not very switchman compatible, so just don't bother trying to use that logic
90
- # raw_records = records_for(loaders)
86
+ # significant changes:
87
+ # * associate shards with records
88
+ # * look on all appropriate shards when loading records
89
+ module LoaderRecords
90
+ def populate_keys_to_load_and_already_loaded_records
91
+ @sharded_keys_to_load = {}
91
92
 
92
93
  loaders.each do |loader|
93
- loader.load_records(nil)
94
- loader.run
94
+ multishard = loader.send(:reflection).options[:multishard]
95
+ belongs_to = loader.send(:reflection).macro == :belongs_to
96
+ loader.owners_by_key.each do |key, owners|
97
+ if (loaded_owner = owners.find { |owner| loader.loaded?(owner) })
98
+ already_loaded_records_by_key[key] = loader.target_for(loaded_owner)
99
+ else
100
+ shard_set = @sharded_keys_to_load[key] ||= Set.new
101
+ owner_key_name = loader.send(:owner_key_name)
102
+ owners.each do |owner|
103
+ if multishard && owner.respond_to?(:associated_shards)
104
+ shard_set.merge(owner.associated_shards.map(&:id))
105
+ elsif belongs_to && owner.class.sharded_column?(owner_key_name)
106
+ shard_set.add(Shard.shard_for(owner[owner_key_name], owner.shard).id)
107
+ elsif belongs_to
108
+ shard_set.add(Shard.current.id)
109
+ else
110
+ shard_set.add(owner.shard.id)
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ @sharded_keys_to_load.delete_if { |key, _shards| already_loaded_records_by_key.include?(key) }
118
+ end
119
+
120
+ def load_records
121
+ ret = []
122
+
123
+ shards_with_keys = @sharded_keys_to_load.each_with_object({}) do |(key, shards), h|
124
+ shards.each { |shard| (h[shard] ||= []) << key }
125
+ end
126
+
127
+ shards_with_keys.each do |shard, keys|
128
+ Shard.lookup(shard).activate do
129
+ scope_was = loader_query.scope
130
+ begin
131
+ loader_query.instance_variable_set(:@scope, loader_query.scope.shard(Shard.current(loader_query.scope.model.connection_class_for_self)))
132
+ ret += loader_query.load_records_for_keys(keys) do |record|
133
+ loaders.each { |l| l.set_inverse(record) }
134
+ end
135
+ ensure
136
+ loader_query.instance_variable_set(:@scope, scope_was)
137
+ end
138
+ end
95
139
  end
140
+
141
+ ret
96
142
  end
97
143
  end
98
144
 
@@ -110,6 +156,26 @@ module Switchman
110
156
  end
111
157
  end
112
158
 
159
+ # Disabling to keep closer to rails original
160
+ # rubocop:disable Naming/AccessorMethodName, Style/GuardClause
161
+ # significant changes:
162
+ # * globalize the key to lookup
163
+ def set_inverse(record)
164
+ global_key = if model.connection_class_for_self == UnshardedRecord
165
+ convert_key(record[association_key_name])
166
+ else
167
+ Shard.global_id_for(record[association_key_name], record.shard)
168
+ end
169
+
170
+ if (owners = owners_by_key[convert_key(global_key)])
171
+ # Processing only the first owner
172
+ # because the record is modified but not an owner
173
+ association = owners.first.association(reflection.name)
174
+ association.set_inverse_instance(record)
175
+ end
176
+ end
177
+ # rubocop:enable Naming/AccessorMethodName, Style/GuardClause
178
+
113
179
  # significant changes:
114
180
  # * partition_by_shard the records_for call
115
181
  # * re-globalize the fetched owner id before looking up in the map
@@ -120,7 +186,9 @@ module Switchman
120
186
  # #compare_by_identity makes such owners different hash keys
121
187
  @records_by_owner = {}.compare_by_identity
122
188
 
123
- if ::Rails.version < '7.0' && owner_keys.empty?
189
+ if ::Rails.version >= '7.0'
190
+ raw_records ||= loader_query.records_for([self])
191
+ elsif owner_keys.empty?
124
192
  raw_records ||= []
125
193
  else
126
194
  # determine the shard to search for each owner
@@ -162,7 +230,7 @@ module Switchman
162
230
  record.shard)
163
231
  end
164
232
 
165
- owners_by_key[convert_key(owner_key)].each do |owner|
233
+ owners_by_key[convert_key(owner_key)]&.each do |owner|
166
234
  entries = (@records_by_owner[owner] ||= [])
167
235
 
168
236
  if reflection.collection? || entries.empty?
@@ -99,7 +99,7 @@ module Switchman
99
99
  if reflection.options[:polymorphic]
100
100
  # a polymorphic association has to be discovered at runtime. This code ends up being something like
101
101
  # context_type.&.constantize&.connection_class_for_self
102
- "read_attribute(:#{reflection.foreign_type})&.constantize&.connection_class_for_self"
102
+ "begin;read_attribute(:#{reflection.foreign_type})&.constantize&.connection_class_for_self;rescue NameError;::ActiveRecord::Base;end"
103
103
  else
104
104
  # otherwise we can just return a symbol for the statically known type of the association
105
105
  "::#{reflection.klass.connection_class_for_self.name}"
@@ -25,7 +25,7 @@ module Switchman
25
25
  # we can make some assumptions about the shard source
26
26
  # (e.g. infer from the primary key or use the current shard)
27
27
 
28
- def execute(*args)
28
+ def execute(*args, &block)
29
29
  params, connection = args
30
30
  klass = @klass
31
31
  target_shard = nil
@@ -40,7 +40,7 @@ module Switchman
40
40
 
41
41
  target_shard.activate(klass.connection_class_for_self) do
42
42
  sql = qualified_query_builder(target_shard, klass).sql_for(bind_values, connection)
43
- klass.find_by_sql(sql, bind_values)
43
+ klass.find_by_sql(sql, bind_values, &block)
44
44
  end
45
45
  end
46
46
 
@@ -66,7 +66,11 @@ module Switchman
66
66
 
67
67
  def primary_value_index
68
68
  primary_ba_index = @bound_attributes.index do |ba|
69
- ba.is_a?(::ActiveRecord::Relation::QueryAttribute) && ba.value.primary
69
+ if ba.value.is_a?(::ActiveRecord::StatementCache::Substitute)
70
+ ba.is_a?(::ActiveRecord::Relation::QueryAttribute) && ba.value.primary
71
+ else
72
+ false
73
+ end
70
74
  end
71
75
  @indexes.index(primary_ba_index) if primary_ba_index
72
76
  end
@@ -50,7 +50,7 @@ module Switchman
50
50
  ::ActiveRecord::Associations::CollectionProxy.include(ActiveRecord::Associations::CollectionProxy)
51
51
 
52
52
  ::ActiveRecord::Associations::Preloader::Association.prepend(ActiveRecord::Associations::Preloader::Association)
53
- ::ActiveRecord::Associations::Preloader::Association::LoaderQuery.prepend(ActiveRecord::Associations::Preloader::Association::LoaderQuery) unless ::Rails.version < '7.0'
53
+ ::ActiveRecord::Associations::Preloader::Association::LoaderRecords.prepend(ActiveRecord::Associations::Preloader::Association::LoaderRecords) unless ::Rails.version < '7.0'
54
54
  ::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecord::AbstractAdapter)
55
55
  ::ActiveRecord::ConnectionAdapters::ConnectionPool.prepend(ActiveRecord::ConnectionPool)
56
56
  ::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecord::QueryCache)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Switchman
4
- VERSION = '3.1.3'
4
+ VERSION = '3.2.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: switchman
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.3
4
+ version: 3.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-08-03 00:00:00.000000000 Z
13
+ date: 2022-11-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord