switchman 2.1.0 → 3.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +10 -2
  3. data/app/models/switchman/shard.rb +270 -343
  4. data/app/models/switchman/unsharded_record.rb +7 -0
  5. data/db/migrate/20130328212039_create_switchman_shards.rb +1 -1
  6. data/db/migrate/20130328224244_create_default_shard.rb +5 -5
  7. data/db/migrate/20161206323434_add_back_default_string_limits_switchman.rb +1 -0
  8. data/db/migrate/20180828183945_add_default_shard_index.rb +2 -2
  9. data/db/migrate/20180828192111_add_timestamps_to_shards.rb +8 -6
  10. data/db/migrate/20190114212900_add_unique_name_indexes.rb +5 -3
  11. data/lib/switchman/action_controller/caching.rb +2 -2
  12. data/lib/switchman/active_record/abstract_adapter.rb +0 -8
  13. data/lib/switchman/active_record/association.rb +78 -89
  14. data/lib/switchman/active_record/attribute_methods.rb +127 -52
  15. data/lib/switchman/active_record/base.rb +83 -67
  16. data/lib/switchman/active_record/calculations.rb +73 -66
  17. data/lib/switchman/active_record/connection_pool.rb +12 -59
  18. data/lib/switchman/active_record/database_configurations/database_config.rb +13 -0
  19. data/lib/switchman/active_record/database_configurations.rb +34 -0
  20. data/lib/switchman/active_record/finder_methods.rb +11 -16
  21. data/lib/switchman/active_record/log_subscriber.rb +4 -8
  22. data/lib/switchman/active_record/migration.rb +19 -45
  23. data/lib/switchman/active_record/model_schema.rb +1 -1
  24. data/lib/switchman/active_record/persistence.rb +11 -6
  25. data/lib/switchman/active_record/postgresql_adapter.rb +33 -161
  26. data/lib/switchman/active_record/predicate_builder.rb +1 -1
  27. data/lib/switchman/active_record/query_cache.rb +18 -19
  28. data/lib/switchman/active_record/query_methods.rb +178 -193
  29. data/lib/switchman/active_record/reflection.rb +7 -22
  30. data/lib/switchman/active_record/relation.rb +32 -29
  31. data/lib/switchman/active_record/spawn_methods.rb +27 -29
  32. data/lib/switchman/active_record/statement_cache.rb +18 -35
  33. data/lib/switchman/active_record/tasks/database_tasks.rb +16 -0
  34. data/lib/switchman/active_record/test_fixtures.rb +43 -0
  35. data/lib/switchman/active_support/cache.rb +3 -5
  36. data/lib/switchman/arel.rb +13 -8
  37. data/lib/switchman/database_server.rb +130 -154
  38. data/lib/switchman/default_shard.rb +52 -16
  39. data/lib/switchman/engine.rb +65 -58
  40. data/lib/switchman/environment.rb +4 -8
  41. data/lib/switchman/errors.rb +1 -0
  42. data/lib/switchman/guard_rail/relation.rb +5 -7
  43. data/lib/switchman/guard_rail.rb +6 -19
  44. data/lib/switchman/r_spec_helper.rb +29 -57
  45. data/lib/switchman/rails.rb +14 -12
  46. data/lib/switchman/sharded_instrumenter.rb +1 -1
  47. data/lib/switchman/standard_error.rb +15 -3
  48. data/lib/switchman/test_helper.rb +5 -3
  49. data/lib/switchman/version.rb +1 -1
  50. data/lib/switchman.rb +3 -3
  51. data/lib/tasks/switchman.rake +61 -72
  52. metadata +90 -48
  53. data/lib/switchman/active_record/batches.rb +0 -11
  54. data/lib/switchman/active_record/connection_handler.rb +0 -190
  55. data/lib/switchman/active_record/where_clause_factory.rb +0 -36
  56. data/lib/switchman/connection_pool_proxy.rb +0 -173
  57. data/lib/switchman/schema_cache.rb +0 -28
@@ -7,19 +7,18 @@ module Switchman
7
7
  return super(id) unless klass.integral_id?
8
8
 
9
9
  if shard_source_value != :implicit
10
- current_shard = Shard.current(klass.shard_category)
11
- result = self.activate do |relation, shard|
10
+ current_shard = Shard.current(klass.connection_classes)
11
+ result = activate do |relation, shard|
12
12
  current_id = Shard.relative_id_for(id, current_shard, shard)
13
13
  # current_id will be nil for non-integral id
14
14
  next unless current_id
15
15
  # skip the shard if the object can't be on it. unless we're only looking at one shard;
16
16
  # we might be expecting a shadow object
17
- next if current_id > Shard::IDS_PER_SHARD && self.all_shards.length > 1
17
+ next if current_id > Shard::IDS_PER_SHARD && all_shards.length > 1
18
+
18
19
  relation.call_super(:find_one, FinderMethods, current_id)
19
20
  end
20
- if result.is_a?(Array)
21
- result = result.first
22
- end
21
+ result = result.first if result.is_a?(Array)
23
22
  # we may have skipped all shards
24
23
  raise_record_not_found_exception!(id, 0, 1) unless result
25
24
  return result
@@ -34,8 +33,8 @@ module Switchman
34
33
  end
35
34
 
36
35
  def find_some_ordered(ids)
37
- current_shard = Shard.current(klass.shard_category)
38
- ids = ids.map{|id| Shard.relative_id_for(id, current_shard, current_shard)}
36
+ current_shard = Shard.current(klass.connection_classes)
37
+ ids = ids.map { |id| Shard.relative_id_for(id, current_shard, current_shard) }
39
38
  super(ids)
40
39
  end
41
40
 
@@ -45,14 +44,12 @@ module Switchman
45
44
 
46
45
  def exists?(conditions = :none)
47
46
  conditions = conditions.id if ::ActiveRecord::Base === conditions
48
- return false if !conditions
47
+ return false unless conditions
49
48
 
50
- relation = ::Rails.version >= "5.2" ?
51
- apply_join_dependency(eager_loading: false) :
52
- apply_join_dependency(self, construct_join_dependency)
49
+ relation = apply_join_dependency(eager_loading: false)
53
50
  return false if ::ActiveRecord::NullRelation === relation
54
51
 
55
- relation = relation.except(:select, :order).select("1 AS one").limit(1)
52
+ relation = relation.except(:select, :order).select('1 AS one').limit(1)
56
53
 
57
54
  case conditions
58
55
  when Array, Hash
@@ -62,9 +59,7 @@ module Switchman
62
59
  end
63
60
 
64
61
  relation.activate do |shard_rel|
65
- return true if ::Rails.version >= "5.2" ?
66
- connection.select_value(shard_rel.arel, "#{name} Exists") :
67
- connection.select_value(shard_rel, "#{name} Exists", shard_rel.bound_attributes)
62
+ return true if connection.select_value(shard_rel.arel, "#{name} Exists")
68
63
  end
69
64
  false
70
65
  end
@@ -14,20 +14,16 @@ module Switchman
14
14
 
15
15
  name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
16
16
  name = "CACHE #{name}" if payload[:cached]
17
- sql = payload[:sql].squeeze(' '.freeze)
17
+ sql = payload[:sql].squeeze(' ')
18
18
  binds = nil
19
19
  shard = payload[:shard]
20
20
  shard = " [#{shard[:database_server_id]}:#{shard[:id]} #{shard[:env]}]" if shard
21
21
 
22
22
  unless (payload[:binds] || []).empty?
23
- use_old_format = (::Rails.version < '5.1.5')
24
- args = use_old_format ?
25
- [payload[:binds], payload[:type_casted_binds]] :
26
- [payload[:type_casted_binds]]
27
- casted_params = type_casted_binds(*args)
28
- binds = " " + payload[:binds].zip(casted_params).map { |attr, value|
23
+ casted_params = type_casted_binds(payload[:type_casted_binds])
24
+ binds = ' ' + payload[:binds].zip(casted_params).map do |attr, value|
29
25
  render_bind(attr, value)
30
- }.inspect
26
+ end.inspect
31
27
  end
32
28
 
33
29
  name = colorize_payload_name(name, payload[:name])
@@ -4,73 +4,47 @@ module Switchman
4
4
  module ActiveRecord
5
5
  module Migration
6
6
  module Compatibility
7
- module V5_0
7
+ module V5_0 # rubocop:disable Naming/ClassAndModuleCamelCase
8
8
  def create_table(*args, **options)
9
- unless options.key?(:id)
10
- options[:id] = :bigserial
11
- end
12
- if block_given?
13
- super do |td|
14
- yield td
15
- end
16
- else
17
- super
18
- end
9
+ options[:id] = :bigserial unless options.key?(:id)
10
+ super
19
11
  end
20
12
  end
21
13
  end
22
14
 
23
15
  def connection
24
16
  conn = super
25
- if conn.shard != ::ActiveRecord::Base.connection_pool.current_pool.shard
26
- ::ActiveRecord::Base.connection_pool.current_pool.switch_database(conn)
27
- end
17
+ ::ActiveRecord::Base.connection_pool.switch_database(conn) if conn.shard != ::ActiveRecord::Base.current_switchman_shard
28
18
  conn
29
19
  end
30
20
  end
31
21
 
32
22
  module Migrator
33
- # significant change: hash shard id, not database name
23
+ # significant change: just return MIGRATOR_SALT directly
24
+ # especially if you're going through pgbouncer, the database
25
+ # name you're accessing may not be consistent. it is NOT allowed
26
+ # to run migrations against multiple shards in the same database
27
+ # concurrently
34
28
  def generate_migrator_advisory_lock_id
35
- shard_name_hash = Zlib.crc32(Shard.current.name)
36
- ::ActiveRecord::Migrator::MIGRATOR_SALT * shard_name_hash
29
+ ::ActiveRecord::Migrator::MIGRATOR_SALT
37
30
  end
38
31
 
39
- if ::Rails.version >= '6.0'
40
- # copy/paste from Rails 6.1
41
- def with_advisory_lock
42
- lock_id = generate_migrator_advisory_lock_id
43
-
44
- with_advisory_lock_connection do |connection|
45
- got_lock = connection.get_advisory_lock(lock_id)
46
- raise ::ActiveRecord::ConcurrentMigrationError unless got_lock
47
- load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
48
- yield
49
- ensure
50
- if got_lock && !connection.release_advisory_lock(lock_id)
51
- raise ::ActiveRecord::ConcurrentMigrationError.new(
52
- ::ActiveRecord::ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
53
- )
54
- end
55
- end
56
- end
32
+ # significant change: strip out prefer_secondary from config
33
+ def with_advisory_lock_connection
34
+ pool = ::ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
35
+ ::ActiveRecord::Base.connection_db_config.configuration_hash.except(:prefer_secondary)
36
+ )
57
37
 
58
- # significant change: strip out prefer_secondary from config
59
- def with_advisory_lock_connection
60
- pool = ::ActiveRecord::ConnectionAdapters::ConnectionHandler.new.establish_connection(
61
- ::ActiveRecord::Base.connection_config.except(:prefer_secondary)
62
- )
63
-
64
- pool.with_connection { |connection| yield(connection) }
65
- ensure
66
- pool&.disconnect!
67
- end
38
+ pool.with_connection { |connection| yield(connection) } # rubocop:disable Style/ExplicitBlockArgument
39
+ ensure
40
+ pool&.disconnect!
68
41
  end
69
42
  end
70
43
 
71
44
  module MigrationContext
72
45
  def migrations
73
46
  return @migrations if instance_variable_defined?(:@migrations)
47
+
74
48
  migrations_cache = Thread.current[:migrations_cache] ||= {}
75
49
  key = Digest::MD5.hexdigest(migration_files.sort.join(','))
76
50
  @migrations = migrations_cache[key] ||= super
@@ -6,7 +6,7 @@ module Switchman
6
6
  module ClassMethods
7
7
  def quoted_table_name
8
8
  @quoted_table_name ||= {}
9
- @quoted_table_name[Shard.current(shard_category).id] ||= connection.quote_table_name(table_name)
9
+ @quoted_table_name[Shard.current(connection_classes).id] ||= connection.quote_table_name(table_name)
10
10
  end
11
11
  end
12
12
  end
@@ -5,14 +5,19 @@ module Switchman
5
5
  module Persistence
6
6
  # touch reads the id attribute directly, so it's not relative to the current shard
7
7
  def touch(*, **)
8
- shard.activate(self.class.shard_category) { super }
8
+ shard.activate(self.class.connection_classes) { super }
9
9
  end
10
10
 
11
- if ::Rails.version >= '5.2'
12
- def update_columns(*)
13
- shard.activate(self.class.shard_category) { super }
14
- end
11
+ def update_columns(*)
12
+ shard.activate(self.class.connection_classes) { super }
13
+ end
14
+
15
+ def delete
16
+ db = shard.database_server
17
+ return db.unguard { super } unless ::GuardRail.environment == db.guard_rail_environment
18
+
19
+ super
15
20
  end
16
21
  end
17
22
  end
18
- end
23
+ end
@@ -9,22 +9,22 @@ module Switchman
9
9
 
10
10
  option_string = options.sum do |key, value|
11
11
  case key
12
- when :owner
13
- " OWNER = \"#{value}\""
14
- when :template
15
- " TEMPLATE = \"#{value}\""
16
- when :encoding
17
- " ENCODING = '#{value}'"
18
- when :collation
19
- " LC_COLLATE = '#{value}'"
20
- when :ctype
21
- " LC_CTYPE = '#{value}'"
22
- when :tablespace
23
- " TABLESPACE = \"#{value}\""
24
- when :connection_limit
25
- " CONNECTION LIMIT = #{value}"
26
- else
27
- ""
12
+ when :owner
13
+ " OWNER = \"#{value}\""
14
+ when :template
15
+ " TEMPLATE = \"#{value}\""
16
+ when :encoding
17
+ " ENCODING = '#{value}'"
18
+ when :collation
19
+ " LC_COLLATE = '#{value}'"
20
+ when :ctype
21
+ " LC_CTYPE = '#{value}'"
22
+ when :tablespace
23
+ " TABLESPACE = \"#{value}\""
24
+ when :connection_limit
25
+ " CONNECTION LIMIT = #{value}"
26
+ else
27
+ ''
28
28
  end
29
29
  end
30
30
 
@@ -32,19 +32,17 @@ module Switchman
32
32
  end
33
33
 
34
34
  # copy/paste; use quote_local_table_name
35
- def drop_database(name) #:nodoc:
35
+ def drop_database(name) # :nodoc:
36
36
  execute "DROP DATABASE IF EXISTS #{quote_local_table_name(name)}"
37
37
  end
38
38
 
39
39
  def current_schemas
40
- select_values("SELECT * FROM unnest(current_schemas(false))")
40
+ select_values('SELECT * FROM unnest(current_schemas(false))')
41
41
  end
42
42
 
43
43
  def extract_schema_qualified_name(string)
44
44
  name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(string.to_s)
45
- if string && !name.schema
46
- name.instance_variable_set(:@schema, shard.name)
47
- end
45
+ name.instance_variable_set(:@schema, shard.name) if string && !name.schema
48
46
  [name.schema, name.identifier]
49
47
  end
50
48
 
@@ -52,12 +50,12 @@ module Switchman
52
50
  def quoted_scope(name = nil, type: nil)
53
51
  schema, name = extract_schema_qualified_name(name)
54
52
  type = \
55
- case type
56
- when "BASE TABLE"
53
+ case type # rubocop:disable Style/HashLikeCase
54
+ when 'BASE TABLE'
57
55
  "'r','p'"
58
- when "VIEW"
56
+ when 'VIEW'
59
57
  "'v','m'"
60
- when "FOREIGN TABLE"
58
+ when 'FOREIGN TABLE'
61
59
  "'f'"
62
60
  end
63
61
  scope = {}
@@ -67,135 +65,10 @@ module Switchman
67
65
  scope
68
66
  end
69
67
 
70
- if ::Rails.version < '6.0'
71
- def tables(name = nil)
72
- query(<<-SQL, 'SCHEMA').map { |row| row[0] }
73
- SELECT tablename
74
- FROM pg_tables
75
- WHERE schemaname = '#{shard.name}'
76
- SQL
77
- end
78
-
79
- def view_exists?(name)
80
- name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
81
- return false unless name.identifier
82
- if !name.schema
83
- name.instance_variable_set(:@schema, shard.name)
84
- end
85
-
86
- select_values(<<-SQL, 'SCHEMA').any?
87
- SELECT c.relname
88
- FROM pg_class c
89
- LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
90
- WHERE c.relkind IN ('v','m') -- (v)iew, (m)aterialized view
91
- AND c.relname = '#{name.identifier}'
92
- AND n.nspname = '#{shard.name}'
93
- SQL
94
- end
95
-
96
- def indexes(table_name)
97
- result = query(<<-SQL, 'SCHEMA')
98
- SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid
99
- FROM pg_class t
100
- INNER JOIN pg_index d ON t.oid = d.indrelid
101
- INNER JOIN pg_class i ON d.indexrelid = i.oid
102
- WHERE i.relkind = 'i'
103
- AND d.indisprimary = 'f'
104
- AND t.relname = '#{table_name}'
105
- AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
106
- ORDER BY i.relname
107
- SQL
108
-
109
-
110
- result.map do |row|
111
- index_name = row[0]
112
- unique = row[1] == true || row[1] == 't'
113
- indkey = row[2].split(" ")
114
- inddef = row[3]
115
- oid = row[4]
116
-
117
- columns = Hash[query(<<-SQL, "SCHEMA")]
118
- SELECT a.attnum, a.attname
119
- FROM pg_attribute a
120
- WHERE a.attrelid = #{oid}
121
- AND a.attnum IN (#{indkey.join(",")})
122
- SQL
123
-
124
- column_names = columns.stringify_keys.values_at(*indkey).compact
125
-
126
- unless column_names.empty?
127
- # add info on sort order for columns (only desc order is explicitly specified, asc is the default)
128
- desc_order_columns = inddef.scan(/(\w+) DESC/).flatten
129
- orders = desc_order_columns.any? ? Hash[desc_order_columns.map {|order_column| [order_column, :desc]}] : {}
130
- where = inddef.scan(/WHERE (.+)$/).flatten[0]
131
- using = inddef.scan(/USING (.+?) /).flatten[0].to_sym
132
-
133
- if ::Rails.version >= "5.2"
134
- ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, orders: orders, where: where, using: using)
135
- else
136
- ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, index_name, unique, column_names, [], orders, where, nil, using)
137
- end
138
- end
139
- end.compact
140
- end
141
-
142
- def index_name_exists?(table_name, index_name, _default = nil)
143
- exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0
144
- SELECT COUNT(*)
145
- FROM pg_class t
146
- INNER JOIN pg_index d ON t.oid = d.indrelid
147
- INNER JOIN pg_class i ON d.indexrelid = i.oid
148
- WHERE i.relkind = 'i'
149
- AND i.relname = '#{index_name}'
150
- AND t.relname = '#{table_name}'
151
- AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = '#{shard.name}' )
152
- SQL
153
- end
154
-
155
- def foreign_keys(table_name)
156
- # mostly copy-pasted from AR - only change is to the nspname condition for qualified names support
157
- fk_info = select_all <<-SQL.strip_heredoc
158
- SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
159
- FROM pg_constraint c
160
- JOIN pg_class t1 ON c.conrelid = t1.oid
161
- JOIN pg_class t2 ON c.confrelid = t2.oid
162
- JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
163
- JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
164
- JOIN pg_namespace t3 ON c.connamespace = t3.oid
165
- WHERE c.contype = 'f'
166
- AND t1.relname = #{quote(table_name)}
167
- AND t3.nspname = '#{shard.name}'
168
- ORDER BY c.conname
169
- SQL
170
-
171
- fk_info.map do |row|
172
- options = {
173
- column: row['column'],
174
- name: row['name'],
175
- primary_key: row['primary_key']
176
- }
177
-
178
- options[:on_delete] = extract_foreign_key_action(row['on_delete'])
179
- options[:on_update] = extract_foreign_key_action(row['on_update'])
180
-
181
- # strip the schema name from to_table if it matches
182
- to_table = row['to_table']
183
- to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(to_table)
184
- if to_table_qualified_name.schema == shard.name
185
- to_table = to_table_qualified_name.identifier
186
- end
187
-
188
- ::ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(table_name, to_table, options)
189
- end
190
- end
191
- else
192
- def foreign_keys(table_name)
193
- super.each do |fk|
194
- to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(fk.to_table)
195
- if to_table_qualified_name.schema == shard.name
196
- fk.to_table = to_table_qualified_name.identifier
197
- end
198
- end
68
+ def foreign_keys(table_name)
69
+ super.each do |fk|
70
+ to_table_qualified_name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(fk.to_table)
71
+ fk.to_table = to_table_qualified_name.identifier if to_table_qualified_name.schema == shard.name
199
72
  end
200
73
  end
201
74
 
@@ -208,10 +81,9 @@ module Switchman
208
81
 
209
82
  def quote_table_name(name)
210
83
  return quote_local_table_name(name) if @use_local_table_name
84
+
211
85
  name = ::ActiveRecord::ConnectionAdapters::PostgreSQL::Utils.extract_schema_qualified_name(name.to_s)
212
- if !name.schema
213
- name.instance_variable_set(:@schema, shard.name)
214
- end
86
+ name.instance_variable_set(:@schema, shard.name) unless name.schema
215
87
  name.quoted
216
88
  end
217
89
 
@@ -219,7 +91,7 @@ module Switchman
219
91
  with_local_table_name(false, &block)
220
92
  end
221
93
 
222
- def with_local_table_name(enable = true)
94
+ def with_local_table_name(enable = true) # rubocop:disable Style/OptionalBooleanParameter
223
95
  old_value = @use_local_table_name
224
96
  @use_local_table_name = enable
225
97
  yield
@@ -228,9 +100,9 @@ module Switchman
228
100
  end
229
101
 
230
102
  def add_index_options(_table_name, _column_name, **)
231
- index_name, index_type, index_columns, index_options, algorithm, using = super
232
- algorithm = nil if DatabaseServer.creating_new_shard && algorithm == "CONCURRENTLY"
233
- [index_name, index_type, index_columns, index_options, algorithm, using]
103
+ index, algorithm, if_not_exists = super
104
+ algorithm = nil if DatabaseServer.creating_new_shard && algorithm == 'CONCURRENTLY'
105
+ [index, algorithm, if_not_exists]
234
106
  end
235
107
 
236
108
  def rename_table(table_name, new_name)
@@ -23,4 +23,4 @@ module Switchman
23
23
  end
24
24
  end
25
25
  end
26
- end
26
+ end
@@ -3,31 +3,30 @@
3
3
  module Switchman
4
4
  module ActiveRecord
5
5
  module QueryCache
6
-
7
6
  private
8
7
 
9
8
  def cache_sql(sql, name, binds)
10
9
  # have to include the shard id in the cache key because of switching dbs on the same connection
11
- sql = "#{self.shard.id}::#{sql}"
10
+ sql = "#{shard.id}::#{sql}"
12
11
  @lock.synchronize do
13
12
  result =
14
- if query_cache[sql].key?(binds)
15
- args = {
16
- sql: sql,
17
- binds: binds,
18
- name: name,
19
- connection_id: object_id,
20
- cached: true
21
- }
22
- args[:type_casted_binds] = -> { type_casted_binds(binds) } if ::Rails.version >= '5.1.5'
23
- ::ActiveSupport::Notifications.instrument(
24
- "sql.active_record",
25
- args
26
- )
27
- query_cache[sql][binds]
28
- else
29
- query_cache[sql][binds] = yield
30
- end
13
+ if query_cache[sql].key?(binds)
14
+ args = {
15
+ sql: sql,
16
+ binds: binds,
17
+ name: name,
18
+ connection_id: object_id,
19
+ cached: true,
20
+ type_casted_binds: -> { type_casted_binds(binds) }
21
+ }
22
+ ::ActiveSupport::Notifications.instrument(
23
+ 'sql.active_record',
24
+ args
25
+ )
26
+ query_cache[sql][binds]
27
+ else
28
+ query_cache[sql][binds] = yield
29
+ end
31
30
  result.dup
32
31
  end
33
32
  end