switchman 3.6.8 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/switchman/active_record/associations.rb +1 -35
- data/lib/switchman/active_record/attribute_methods.rb +30 -28
- data/lib/switchman/active_record/base.rb +1 -11
- data/lib/switchman/active_record/calculations.rb +4 -13
- data/lib/switchman/active_record/connection_pool.rb +1 -1
- data/lib/switchman/active_record/relation.rb +1 -1
- data/lib/switchman/engine.rb +4 -17
- data/lib/switchman/sharded_instrumenter.rb +1 -5
- data/lib/switchman/version.rb +1 -1
- data/lib/tasks/switchman.rake +3 -33
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd3fc41cd455d5855db84fd49d132dca58c824dbe50e49ea4ab7c4cd0ee24d00
|
4
|
+
data.tar.gz: df1df2b43f521a5b5e424165ac167d2de351c4800db6fe50b5d83a78e8e17e16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b721c57764dc47c2da10b027b63fdeed4795c349b2dec36b0d440e98ff0294355a4bbb03d2176f30883de0b842e2f4a47f27ea2fa2f56405594f53d4a278f6c
|
7
|
+
data.tar.gz: 2729dfb39b1e3d8e3df84bcf1bd321ac39de73e552d8a6c0f15f48f6b9fdb47611a076f8e11fbcbfeb4fd8097c2e6a49a2eab7d76942af92ed769c03b1b9f7d0
|
@@ -203,41 +203,7 @@ module Switchman
|
|
203
203
|
# #compare_by_identity makes such owners different hash keys
|
204
204
|
@records_by_owner = {}.compare_by_identity
|
205
205
|
|
206
|
-
|
207
|
-
raw_records ||= loader_query.records_for([self])
|
208
|
-
elsif owner_keys.empty?
|
209
|
-
raw_records ||= []
|
210
|
-
else
|
211
|
-
# determine the shard to search for each owner
|
212
|
-
if reflection.macro == :belongs_to
|
213
|
-
# for belongs_to, it's the shard of the foreign_key
|
214
|
-
partition_proc = lambda do |owner|
|
215
|
-
if owner.class.sharded_column?(owner_key_name)
|
216
|
-
Shard.shard_for(owner[owner_key_name], owner.shard)
|
217
|
-
else
|
218
|
-
Shard.current
|
219
|
-
end
|
220
|
-
end
|
221
|
-
elsif !reflection.options[:multishard]
|
222
|
-
# for non-multishard associations, it's *just* the owner's shard
|
223
|
-
partition_proc = ->(owner) { owner.shard }
|
224
|
-
end
|
225
|
-
|
226
|
-
raw_records ||= Shard.partition_by_shard(owners, partition_proc) do |partitioned_owners|
|
227
|
-
relative_owner_keys = partitioned_owners.map do |owner|
|
228
|
-
key = owner[owner_key_name]
|
229
|
-
if key && owner.class.sharded_column?(owner_key_name)
|
230
|
-
key = Shard.relative_id_for(key,
|
231
|
-
owner.shard,
|
232
|
-
Shard.current(klass.connection_class_for_self))
|
233
|
-
end
|
234
|
-
convert_key(key)
|
235
|
-
end
|
236
|
-
relative_owner_keys.compact!
|
237
|
-
relative_owner_keys.uniq!
|
238
|
-
records_for(relative_owner_keys)
|
239
|
-
end
|
240
|
-
end
|
206
|
+
raw_records ||= loader_query.records_for([self])
|
241
207
|
|
242
208
|
@preloaded_records = raw_records.select do |record|
|
243
209
|
assignments = false
|
@@ -26,10 +26,10 @@ module Switchman
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def define_attribute_methods
|
29
|
-
super
|
29
|
+
result = super
|
30
30
|
# ensure that we're using the sharded attribute method
|
31
31
|
# and not the silly one in AR::AttributeMethods::PrimaryKey
|
32
|
-
return unless sharded_column?(@primary_key)
|
32
|
+
return result unless sharded_column?(@primary_key)
|
33
33
|
|
34
34
|
class_eval(
|
35
35
|
build_sharded_getter("id",
|
@@ -41,6 +41,7 @@ module Switchman
|
|
41
41
|
class_eval(build_sharded_setter("id", @primary_key, "::#{connection_class_for_self.name}"),
|
42
42
|
__FILE__,
|
43
43
|
__LINE__)
|
44
|
+
result
|
44
45
|
end
|
45
46
|
|
46
47
|
protected
|
@@ -55,19 +56,20 @@ module Switchman
|
|
55
56
|
end
|
56
57
|
|
57
58
|
def define_cached_method(owner, name, namespace:, as:, &block)
|
58
|
-
if ::Rails.version < "7.
|
59
|
-
|
60
|
-
|
59
|
+
if ::Rails.version < "7.1.4"
|
60
|
+
# https://github.com/rails/rails/commit/a2a12fc2e3f4e6d06f81d4c74c88f8e6b3369ee6#diff-5b59ece6d9396b596f06271cec0ea726e3360911383511c49b1a66f454bfc2b6L30
|
61
|
+
# These arguments were effectively swapped in Rails 7.1.4, so previous versions need them reversed
|
62
|
+
owner.define_cached_method(as, namespace: namespace, as: name, &block)
|
61
63
|
else
|
62
64
|
owner.define_cached_method(name, namespace: namespace, as: as, &block)
|
63
65
|
end
|
64
66
|
end
|
65
67
|
|
66
|
-
def define_method_global_attribute(attr_name, owner:)
|
68
|
+
def define_method_global_attribute(attr_name, owner:, as: attr_name)
|
67
69
|
if sharded_column?(attr_name)
|
68
70
|
define_cached_method(owner,
|
69
|
-
"
|
70
|
-
as: "
|
71
|
+
"sharded_global_#{attr_name}",
|
72
|
+
as: "global_#{as}",
|
71
73
|
namespace: :switchman) do |batch|
|
72
74
|
batch << <<-RUBY
|
73
75
|
def sharded_global_#{attr_name}
|
@@ -84,11 +86,11 @@ module Switchman
|
|
84
86
|
end
|
85
87
|
end
|
86
88
|
|
87
|
-
def define_method_local_attribute(attr_name, owner:)
|
89
|
+
def define_method_local_attribute(attr_name, owner:, as: attr_name)
|
88
90
|
if sharded_column?(attr_name)
|
89
91
|
define_cached_method(owner,
|
90
|
-
"
|
91
|
-
as: "
|
92
|
+
"sharded_local_#{attr_name}",
|
93
|
+
as: "local_#{as}",
|
92
94
|
namespace: :switchman) do |batch|
|
93
95
|
batch << <<-RUBY
|
94
96
|
def sharded_local_#{attr_name}
|
@@ -127,21 +129,21 @@ module Switchman
|
|
127
129
|
end
|
128
130
|
end
|
129
131
|
|
130
|
-
def define_method_attribute(attr_name, owner:)
|
132
|
+
def define_method_attribute(attr_name, owner:, as: attr_name)
|
131
133
|
if sharded_column?(attr_name)
|
132
134
|
reflection = reflection_for_integer_attribute(attr_name)
|
133
135
|
class_name = connection_class_for_self_code_for_reflection(reflection)
|
134
136
|
safe_class_name = class_name.unpack1("h*")
|
135
137
|
define_cached_method(owner,
|
136
|
-
attr_name,
|
137
|
-
as:
|
138
|
+
"sharded_#{safe_class_name}_#{attr_name}",
|
139
|
+
as: as,
|
138
140
|
namespace: :switchman) do |batch|
|
139
141
|
batch << build_sharded_getter("sharded_#{safe_class_name}_#{attr_name}",
|
140
|
-
"original_#{
|
142
|
+
"original_#{as}",
|
141
143
|
class_name)
|
142
144
|
end
|
143
145
|
else
|
144
|
-
define_cached_method(owner,
|
146
|
+
define_cached_method(owner, "plain_#{attr_name}", as: as, namespace: :switchman) do |batch|
|
145
147
|
batch << <<-RUBY
|
146
148
|
def plain_#{attr_name}
|
147
149
|
_read_attribute("#{attr_name}") { |n| missing_attribute(n, caller) }
|
@@ -174,19 +176,19 @@ module Switchman
|
|
174
176
|
RUBY
|
175
177
|
end
|
176
178
|
|
177
|
-
def define_method_attribute=(attr_name, owner:)
|
179
|
+
def define_method_attribute=(attr_name, owner:, as: attr_name)
|
178
180
|
if sharded_column?(attr_name)
|
179
181
|
reflection = reflection_for_integer_attribute(attr_name)
|
180
182
|
class_name = connection_class_for_self_code_for_reflection(reflection)
|
181
183
|
safe_class_name = class_name.unpack1("h*")
|
182
184
|
define_cached_method(owner,
|
183
|
-
"#{attr_name}=",
|
184
|
-
as: "
|
185
|
+
"sharded_#{safe_class_name}_#{attr_name}=",
|
186
|
+
as: "#{as}=",
|
185
187
|
namespace: :switchman) do |batch|
|
186
188
|
batch << build_sharded_setter("sharded_#{safe_class_name}_#{attr_name}", attr_name, class_name)
|
187
189
|
end
|
188
190
|
else
|
189
|
-
define_cached_method(owner, "#{attr_name}=", as: "
|
191
|
+
define_cached_method(owner, "plain_#{attr_name}=", as: "#{as}=", namespace: :switchman) do |batch|
|
190
192
|
batch << <<-RUBY
|
191
193
|
def plain_#{attr_name}=(new_value)
|
192
194
|
_write_attribute('#{attr_name}', new_value)
|
@@ -204,11 +206,11 @@ module Switchman
|
|
204
206
|
RUBY
|
205
207
|
end
|
206
208
|
|
207
|
-
def define_method_original_attribute(attr_name, owner:)
|
209
|
+
def define_method_original_attribute(attr_name, owner:, as: attr_name)
|
208
210
|
if sharded_column?(attr_name)
|
209
211
|
define_cached_method(owner,
|
210
|
-
"
|
211
|
-
as: "
|
212
|
+
"sharded_original_#{attr_name}",
|
213
|
+
as: "original_#{as}",
|
212
214
|
namespace: :switchman) do |batch|
|
213
215
|
batch << <<-RUBY
|
214
216
|
def sharded_original_#{attr_name}
|
@@ -221,12 +223,12 @@ module Switchman
|
|
221
223
|
end
|
222
224
|
end
|
223
225
|
|
224
|
-
def define_method_original_attribute=(attr_name, owner:)
|
226
|
+
def define_method_original_attribute=(attr_name, owner:, as: attr_name)
|
225
227
|
return unless sharded_column?(attr_name)
|
226
228
|
|
227
229
|
define_cached_method(owner,
|
228
|
-
"
|
229
|
-
as: "
|
230
|
+
"sharded_original_#{attr_name}=",
|
231
|
+
as: "original_#{as}=",
|
230
232
|
namespace: :switchman) do |batch|
|
231
233
|
batch << <<-RUBY
|
232
234
|
def sharded_original_#{attr_name}=(new_value)
|
@@ -240,8 +242,8 @@ module Switchman
|
|
240
242
|
return if columns_hash["#{prefix}_#{attr_name}"] || attr_name == "id"
|
241
243
|
|
242
244
|
define_cached_method(owner,
|
243
|
-
"#{prefix}_#{attr_name}",
|
244
|
-
as: "
|
245
|
+
"unsharded_#{prefix}_#{attr_name}",
|
246
|
+
as: "#{prefix}_#{attr_name}",
|
245
247
|
namespace: :switchman) do |batch|
|
246
248
|
batch << <<-RUBY
|
247
249
|
def unsharded_#{prefix}_#{attr_name}
|
@@ -136,11 +136,7 @@ module Switchman
|
|
136
136
|
end
|
137
137
|
|
138
138
|
def connected_to_stack
|
139
|
-
has_own_stack =
|
140
|
-
Thread.current.thread_variable?(:ar_connected_to_stack)
|
141
|
-
else
|
142
|
-
::ActiveSupport::IsolatedExecutionState.key?(:active_record_connected_to_stack)
|
143
|
-
end
|
139
|
+
has_own_stack = ::ActiveSupport::IsolatedExecutionState.key?(:active_record_connected_to_stack)
|
144
140
|
|
145
141
|
ret = super
|
146
142
|
return ret if has_own_stack
|
@@ -189,12 +185,6 @@ module Switchman
|
|
189
185
|
|
190
186
|
Shard.default
|
191
187
|
end
|
192
|
-
|
193
|
-
if ::Rails.version < "7.0"
|
194
|
-
def connection_class_for_self
|
195
|
-
connection_classes
|
196
|
-
end
|
197
|
-
end
|
198
188
|
end
|
199
189
|
|
200
190
|
def self.prepended(klass)
|
@@ -148,19 +148,10 @@ module Switchman
|
|
148
148
|
private
|
149
149
|
|
150
150
|
def type_cast_calculated_value_switchman(value, column_name, operation)
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
lookup_cast_type_from_join_dependencies(column_name.to_s) || ::ActiveRecord::Type.default_value
|
156
|
-
type.deserialize(val)
|
157
|
-
end
|
158
|
-
else
|
159
|
-
column = aggregate_column(column_name)
|
160
|
-
type ||= column.try(:type_caster) ||
|
161
|
-
lookup_cast_type_from_join_dependencies(column_name.to_s) || ::ActiveRecord::Type.default_value
|
162
|
-
type_cast_calculated_value(value, operation, type)
|
163
|
-
end
|
151
|
+
column = aggregate_column(column_name)
|
152
|
+
type ||= column.try(:type_caster) ||
|
153
|
+
lookup_cast_type_from_join_dependencies(column_name.to_s) || ::ActiveRecord::Type.default_value
|
154
|
+
type_cast_calculated_value(value, operation, type)
|
164
155
|
end
|
165
156
|
|
166
157
|
def column_name_for(field)
|
data/lib/switchman/engine.rb
CHANGED
@@ -10,20 +10,9 @@ module Switchman
|
|
10
10
|
|
11
11
|
::GuardRail.singleton_class.prepend(GuardRail::ClassMethods)
|
12
12
|
|
13
|
-
# after :initialize_dependency_mechanism to ensure autoloading is
|
14
|
-
# configured for any downstream initializers that care. In rails 7.0 we
|
15
|
-
# should be able to just use an explicit after on configuring the once
|
16
|
-
# autoloaders and not need to go monkey around with initializer order
|
17
|
-
if ::Rails.version < "7.0"
|
18
|
-
initialize_dependency_mechanism = ::Rails::Application::Bootstrap.initializers.find do |i|
|
19
|
-
i.name == :initialize_dependency_mechanism
|
20
|
-
end
|
21
|
-
initialize_dependency_mechanism.instance_variable_get(:@options)[:after] = :set_autoload_paths
|
22
|
-
end
|
23
|
-
|
24
13
|
initializer "switchman.active_record_patch",
|
25
14
|
before: "active_record.initialize_database",
|
26
|
-
after:
|
15
|
+
after: :setup_once_autoloader do
|
27
16
|
::ActiveSupport.on_load(:active_record) do
|
28
17
|
# Switchman requires postgres, so just always load the pg adapter
|
29
18
|
require "active_record/connection_adapters/postgresql_adapter"
|
@@ -54,11 +43,9 @@ module Switchman
|
|
54
43
|
::ActiveRecord::Associations::CollectionProxy.include(ActiveRecord::Associations::CollectionProxy)
|
55
44
|
|
56
45
|
::ActiveRecord::Associations::Preloader::Association.prepend(ActiveRecord::Associations::Preloader::Association)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
)
|
61
|
-
end
|
46
|
+
::ActiveRecord::Associations::Preloader::Association::LoaderRecords.prepend(
|
47
|
+
ActiveRecord::Associations::Preloader::Association::LoaderRecords
|
48
|
+
)
|
62
49
|
::ActiveRecord::ConnectionAdapters::AbstractAdapter.prepend(ActiveRecord::AbstractAdapter)
|
63
50
|
unless ::Rails.version < "7.1"
|
64
51
|
::ActiveRecord::ConnectionAdapters::ConnectionHandler.prepend(ActiveRecord::ConnectionHandler)
|
@@ -16,11 +16,7 @@ module Switchman
|
|
16
16
|
payload[:shard] = {
|
17
17
|
database_server_id: shard.database_server.id,
|
18
18
|
id: shard.id,
|
19
|
-
env:
|
20
|
-
@shard_host.pool.connection_klass&.current_role
|
21
|
-
else
|
22
|
-
@shard_host.pool.connection_class&.current_role
|
23
|
-
end
|
19
|
+
env: @shard_host.pool.connection_class&.current_role
|
24
20
|
}
|
25
21
|
end
|
26
22
|
super(name, payload)
|
data/lib/switchman/version.rb
CHANGED
data/lib/tasks/switchman.rake
CHANGED
@@ -1,16 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# In rails 7.0+ if you have only 1 db in the env it doesn't try to do explicit activation
|
4
|
-
# (and for rails purposes we only have one db per env because each database server is a separate env)
|
5
|
-
if Rails.version < "7.0"
|
6
|
-
task_prefix = Rake::Task.task_defined?("app:db:migrate") ? "app:db" : "db"
|
7
|
-
Rake::Task["#{task_prefix}:migrate"].clear_actions.enhance do
|
8
|
-
ActiveRecord::Tasks::DatabaseTasks.migrate
|
9
|
-
# Ensure this doesn't blow up when running inside the dummy app
|
10
|
-
Rake::Task["#{task_prefix}:_dump"].invoke
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
3
|
module Switchman
|
15
4
|
module Rake
|
16
5
|
def self.filter_database_servers
|
@@ -265,28 +254,9 @@ module Switchman
|
|
265
254
|
|
266
255
|
module ActiveRecord
|
267
256
|
module PostgreSQLDatabaseTasks
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
args = ["--schema-only", "--no-privileges", "--no-owner", "--file", filename]
|
272
|
-
args.concat(Array(extra_flags)) if extra_flags
|
273
|
-
shard = Shard.current.name
|
274
|
-
serialized_search_path = shard
|
275
|
-
args << "--schema=#{Shellwords.escape(shard)}"
|
276
|
-
|
277
|
-
ignore_tables = ::ActiveRecord::SchemaDumper.ignore_tables
|
278
|
-
args += ignore_tables.flat_map { |table| ["-T", table] } if ignore_tables.any?
|
279
|
-
|
280
|
-
args << db_config.database
|
281
|
-
run_cmd("pg_dump", args, "dumping")
|
282
|
-
remove_sql_header_comments(filename)
|
283
|
-
File.open(filename, "a") { |f| f << "SET search_path TO #{serialized_search_path};\n\n" }
|
284
|
-
end
|
285
|
-
else
|
286
|
-
def structure_dump(...)
|
287
|
-
::ActiveRecord.dump_schemas = Switchman::Shard.current.name
|
288
|
-
super
|
289
|
-
end
|
257
|
+
def structure_dump(...)
|
258
|
+
::ActiveRecord.dump_schemas = Switchman::Shard.current.name
|
259
|
+
super
|
290
260
|
end
|
291
261
|
end
|
292
262
|
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:
|
4
|
+
version: 4.0.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: 2025-
|
13
|
+
date: 2025-02-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ">="
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: '7.0'
|
22
22
|
- - "<"
|
23
23
|
- !ruby/object:Gem::Version
|
24
24
|
version: '7.2'
|
@@ -28,7 +28,7 @@ dependencies:
|
|
28
28
|
requirements:
|
29
29
|
- - ">="
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
-
version:
|
31
|
+
version: '7.0'
|
32
32
|
- - "<"
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '7.2'
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '7.0'
|
70
70
|
- - "<"
|
71
71
|
- !ruby/object:Gem::Version
|
72
72
|
version: '7.2'
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
requirements:
|
77
77
|
- - ">="
|
78
78
|
- !ruby/object:Gem::Version
|
79
|
-
version: '
|
79
|
+
version: '7.0'
|
80
80
|
- - "<"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '7.2'
|