switchman 1.16.0 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/app/models/switchman/shard.rb +10 -5
  3. data/db/migrate/20130328212039_create_switchman_shards.rb +2 -0
  4. data/db/migrate/20130328224244_create_default_shard.rb +3 -1
  5. data/db/migrate/20161206323434_add_back_default_string_limits_switchman.rb +2 -0
  6. data/db/migrate/20180828183945_add_default_shard_index.rb +2 -0
  7. data/db/migrate/20180828192111_add_timestamps_to_shards.rb +2 -0
  8. data/db/migrate/20190114212900_add_unique_name_indexes.rb +2 -0
  9. data/lib/switchman.rb +3 -1
  10. data/lib/switchman/action_controller/caching.rb +2 -0
  11. data/lib/switchman/active_record/abstract_adapter.rb +8 -2
  12. data/lib/switchman/active_record/association.rb +10 -4
  13. data/lib/switchman/active_record/attribute_methods.rb +2 -0
  14. data/lib/switchman/active_record/base.rb +13 -11
  15. data/lib/switchman/active_record/batches.rb +2 -0
  16. data/lib/switchman/active_record/calculations.rb +2 -0
  17. data/lib/switchman/active_record/connection_handler.rb +8 -6
  18. data/lib/switchman/active_record/connection_pool.rb +2 -0
  19. data/lib/switchman/active_record/finder_methods.rb +2 -0
  20. data/lib/switchman/active_record/log_subscriber.rb +2 -0
  21. data/lib/switchman/active_record/migration.rb +3 -1
  22. data/lib/switchman/active_record/model_schema.rb +2 -0
  23. data/lib/switchman/active_record/persistence.rb +3 -1
  24. data/lib/switchman/active_record/postgresql_adapter.rb +3 -1
  25. data/lib/switchman/active_record/predicate_builder.rb +2 -0
  26. data/lib/switchman/active_record/query_cache.rb +2 -0
  27. data/lib/switchman/active_record/query_methods.rb +121 -72
  28. data/lib/switchman/active_record/reflection.rb +2 -0
  29. data/lib/switchman/active_record/relation.rb +7 -5
  30. data/lib/switchman/active_record/spawn_methods.rb +2 -0
  31. data/lib/switchman/active_record/statement_cache.rb +3 -1
  32. data/lib/switchman/active_record/table_definition.rb +4 -2
  33. data/lib/switchman/active_record/type_caster.rb +2 -0
  34. data/lib/switchman/active_record/where_clause_factory.rb +2 -0
  35. data/lib/switchman/active_support/cache.rb +4 -2
  36. data/lib/switchman/arel.rb +2 -0
  37. data/lib/switchman/call_super.rb +2 -0
  38. data/lib/switchman/connection_pool_proxy.rb +13 -11
  39. data/lib/switchman/database_server.rb +18 -16
  40. data/lib/switchman/default_shard.rb +2 -0
  41. data/lib/switchman/engine.rb +10 -8
  42. data/lib/switchman/environment.rb +2 -0
  43. data/lib/switchman/errors.rb +2 -0
  44. data/lib/switchman/{shackles.rb → guard_rail.rb} +6 -4
  45. data/lib/switchman/{shackles → guard_rail}/relation.rb +7 -5
  46. data/lib/switchman/open4.rb +2 -0
  47. data/lib/switchman/r_spec_helper.rb +7 -5
  48. data/lib/switchman/rails.rb +2 -0
  49. data/lib/switchman/schema_cache.rb +2 -0
  50. data/lib/switchman/sharded_instrumenter.rb +3 -1
  51. data/lib/switchman/standard_error.rb +2 -0
  52. data/lib/switchman/test_helper.rb +5 -3
  53. data/lib/switchman/version.rb +3 -1
  54. data/lib/tasks/switchman.rake +3 -3
  55. metadata +30 -16
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module Reflection
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module Relation
@@ -5,7 +7,7 @@ module Switchman
5
7
  klass::SINGLE_VALUE_METHODS.concat [ :shard, :shard_source ]
6
8
  end
7
9
 
8
- def initialize(*args)
10
+ def initialize(*, **)
9
11
  super
10
12
  self.shard_value = Shard.current(klass ? klass.shard_category : :primary) unless shard_value
11
13
  self.shard_source_value = :implicit unless shard_source_value
@@ -17,7 +19,7 @@ module Switchman
17
19
  result
18
20
  end
19
21
 
20
- def merge(*args)
22
+ def merge(*)
21
23
  relation = super
22
24
  if relation.shard_value != self.shard_value && relation.shard_source_value == :implicit
23
25
  relation.shard_value = self.shard_value
@@ -26,15 +28,15 @@ module Switchman
26
28
  relation
27
29
  end
28
30
 
29
- def new(*args, &block)
31
+ def new(*, &block)
30
32
  primary_shard.activate(klass.shard_category) { super }
31
33
  end
32
34
 
33
- def create(*args, &block)
35
+ def create(*, &block)
34
36
  primary_shard.activate(klass.shard_category) { super }
35
37
  end
36
38
 
37
- def create!(*args, &block)
39
+ def create!(*, &block)
38
40
  primary_shard.activate(klass.shard_category) { super }
39
41
  end
40
42
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module SpawnMethods
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module StatementCache
4
6
  module ClassMethods
5
- def create(connection, block = Proc.new)
7
+ def create(connection, &block)
6
8
  relation = block.call ::ActiveRecord::StatementCache::Params.new
7
9
 
8
10
  if ::Rails.version >= "5.2"
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module TableDefinition
4
- def column(name, type, options = {})
5
- Engine.foreign_key_check(name, type, options)
6
+ def column(name, type, limit: nil, **)
7
+ Engine.foreign_key_check(name, type, limit: limit)
6
8
  super
7
9
  end
8
10
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module TypeCaster
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveRecord
3
5
  module WhereClauseFactory
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module ActiveSupport
3
5
  module Cache
@@ -15,12 +17,12 @@ module Switchman
15
17
  end
16
18
 
17
19
  module RedisCacheStore
18
- def clear(options = {})
20
+ def clear(namespace: nil, **)
19
21
  # RedisCacheStore tries to be smart and only clear the cache under your namespace, if you have one set
20
22
  # unfortunately, it uses the keys command, which is extraordinarily inefficient in a large redis instance
21
23
  # fortunately, we can assume we control the entire instance, because we set up the namespacing, so just
22
24
  # always unset it temporarily for clear calls
23
- options[:namespace] = nil
25
+ namespace = nil
24
26
  super
25
27
  end
26
28
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module Arel
3
5
  module Table
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  module CallSuper
3
5
  def super_method_above(method_name, above_module)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'switchman/schema_cache'
2
4
 
3
5
  module Switchman
@@ -37,13 +39,13 @@ module Switchman
37
39
  Shard.current(@category)
38
40
  end
39
41
 
40
- def active_shackles_environment
41
- ::Rails.env.test? ? :master : active_shard.database_server.shackles_environment
42
+ def active_guard_rail_environment
43
+ ::Rails.env.test? ? :primary : active_shard.database_server.guard_rail_environment
42
44
  end
43
45
 
44
46
  def current_pool
45
47
  current_active_shard = active_shard
46
- pool = self.default_pool if current_active_shard.database_server == Shard.default.database_server && active_shackles_environment == :master && (current_active_shard.default? || current_active_shard.database_server.shareable?)
48
+ pool = self.default_pool if current_active_shard.database_server == Shard.default.database_server && active_guard_rail_environment == :primary && (current_active_shard.default? || current_active_shard.database_server.shareable?)
47
49
  pool = @connection_pools[pool_key] ||= create_pool unless pool
48
50
  pool.shard = current_active_shard
49
51
  pool
@@ -60,8 +62,8 @@ module Switchman
60
62
  connection.instance_variable_set(:@schema_cache, @schema_cache) unless ::Rails.version >= '6'
61
63
  connection
62
64
  rescue ConnectionError
63
- raise if active_shard.database_server == Shard.default.database_server && active_shackles_environment == :master
64
- configs = active_shard.database_server.config(active_shackles_environment)
65
+ raise if active_shard.database_server == Shard.default.database_server && active_guard_rail_environment == :primary
66
+ configs = active_shard.database_server.config(active_guard_rail_environment)
65
67
  raise unless configs.is_a?(Array)
66
68
  configs.each_with_index do |config, idx|
67
69
  pool = create_pool(config.dup)
@@ -120,7 +122,7 @@ module Switchman
120
122
  end
121
123
 
122
124
  def pool_key
123
- [active_shackles_environment,
125
+ [active_guard_rail_environment,
124
126
  active_shard.database_server.shareable? ? active_shard.database_server.pool_key : active_shard]
125
127
  end
126
128
 
@@ -128,7 +130,7 @@ module Switchman
128
130
  shard = active_shard
129
131
  unless config
130
132
  if shard != Shard.default
131
- config = shard.database_server.config(active_shackles_environment)
133
+ config = shard.database_server.config(active_guard_rail_environment)
132
134
  config = config.first if config.is_a?(Array)
133
135
  config = config.dup
134
136
  else
@@ -138,10 +140,10 @@ module Switchman
138
140
  # different models could be using different configs on the default
139
141
  # shard, and database server wouldn't know about that
140
142
  config = default_pool.spec.instance_variable_get(:@config)
141
- if config[active_shackles_environment].is_a?(Hash)
142
- config = config.merge(config[active_shackles_environment])
143
- elsif config[active_shackles_environment].is_a?(Array)
144
- config = config.merge(config[active_shackles_environment].first)
143
+ if config[active_guard_rail_environment].is_a?(Hash)
144
+ config = config.merge(config[active_guard_rail_environment])
145
+ elsif config[active_guard_rail_environment].is_a?(Array)
146
+ config = config.merge(config[active_guard_rail_environment].first)
145
147
  else
146
148
  config = config.dup
147
149
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "securerandom"
2
4
 
3
5
  module Switchman
@@ -69,12 +71,12 @@ module Switchman
69
71
  @fake
70
72
  end
71
73
 
72
- def config(environment = :master)
74
+ def config(environment = :primary)
73
75
  @configs[environment] ||= begin
74
76
  if @config[environment].is_a?(Array)
75
77
  @config[environment].map do |config|
76
78
  config = @config.merge((config || {}).symbolize_keys)
77
- # make sure Shackles doesn't get any brilliant ideas about choosing the first possible server
79
+ # make sure GuardRail doesn't get any brilliant ideas about choosing the first possible server
78
80
  config.delete(environment)
79
81
  config
80
82
  end
@@ -86,33 +88,33 @@ module Switchman
86
88
  end
87
89
  end
88
90
 
89
- def shackles_environment
90
- @shackles_environment || ::Shackles.environment
91
+ def guard_rail_environment
92
+ @guard_rail_environment || ::GuardRail.environment
91
93
  end
92
94
 
93
95
  # locks this db to a specific environment, except for
94
96
  # when doing writes (then it falls back to the current
95
- # value of Shackles.environment)
96
- def shackle!(environment = :slave)
97
- @shackles_environment = environment
97
+ # value of GuardRail.environment)
98
+ def guard!(environment = :secondary)
99
+ @guard_rail_environment = environment
98
100
  end
99
101
 
100
- def unshackle!
101
- @shackles_environment = nil
102
+ def unguard!
103
+ @guard_rail_environment = nil
102
104
  end
103
105
 
104
- def unshackle
105
- old_env = @shackles_environment
106
- unshackle!
106
+ def unguard
107
+ old_env = @guard_rail_environment
108
+ unguard!
107
109
  yield
108
110
  ensure
109
- shackle!(old_env)
111
+ guard!(old_env)
110
112
  end
111
113
 
112
114
  def shareable?
113
115
  @shareable_environment_key ||= []
114
- environment = shackles_environment
115
- explicit_user = ::Shackles.global_config[:username]
116
+ environment = guard_rail_environment
117
+ explicit_user = ::GuardRail.global_config[:username]
116
118
  return @shareable if @shareable_environment_key == [environment, explicit_user]
117
119
  @shareable_environment_key = [environment, explicit_user]
118
120
  if explicit_user
@@ -190,7 +192,7 @@ module Switchman
190
192
  begin
191
193
  self.class.creating_new_shard = true
192
194
  shard.activate(*Shard.categories) do
193
- ::Shackles.activate(:deploy) do
195
+ ::GuardRail.activate(:deploy) do
194
196
  begin
195
197
  if create_statement
196
198
  if (::ActiveRecord::Base.connection.select_value("SELECT 1 FROM pg_namespace WHERE nspname=#{::ActiveRecord::Base.connection.quote(name)}"))
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'switchman/database_server'
2
4
 
3
5
  module Switchman
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  class Engine < ::Rails::Engine
3
5
  isolate_namespace Switchman
@@ -87,7 +89,7 @@ module Switchman
87
89
  require "switchman/arel"
88
90
  require "switchman/call_super"
89
91
  require "switchman/rails"
90
- require "switchman/shackles/relation"
92
+ require "switchman/guard_rail/relation"
91
93
  require_dependency "switchman/shard"
92
94
  require "switchman/standard_error"
93
95
 
@@ -133,7 +135,7 @@ module Switchman
133
135
  ::ActiveRecord::Relation.prepend(ActiveRecord::Calculations)
134
136
  ::ActiveRecord::Relation.include(ActiveRecord::FinderMethods)
135
137
  ::ActiveRecord::Relation.include(ActiveRecord::QueryMethods)
136
- ::ActiveRecord::Relation.prepend(Shackles::Relation)
138
+ ::ActiveRecord::Relation.prepend(GuardRail::Relation)
137
139
  ::ActiveRecord::Relation.prepend(ActiveRecord::Relation)
138
140
  ::ActiveRecord::Relation.include(ActiveRecord::SpawnMethods)
139
141
  ::ActiveRecord::Relation.include(CallSuper)
@@ -150,8 +152,8 @@ module Switchman
150
152
  end
151
153
  end
152
154
 
153
- def self.foreign_key_check(name, type, options)
154
- if name.to_s =~ /_id\z/ && type.to_s == 'integer' && options[:limit].to_i < 8
155
+ def self.foreign_key_check(name, type, limit: nil)
156
+ if name.to_s =~ /_id\z/ && type.to_s == 'integer' && limit.to_i < 8
155
157
  puts "WARNING: All foreign keys need to be 8-byte integers. #{name} looks like a foreign key. If so, please add the option: `:limit => 8`"
156
158
  end
157
159
  end
@@ -185,15 +187,15 @@ module Switchman
185
187
  end
186
188
  end
187
189
 
188
- initializer 'switchman.extend_shackles', :before => "switchman.extend_ar" do
190
+ initializer 'switchman.extend_guard_rail', :before => "switchman.extend_ar" do
189
191
  ::ActiveSupport.on_load(:active_record) do
190
- require "switchman/shackles"
192
+ require "switchman/guard_rail"
191
193
 
192
- ::Shackles.singleton_class.prepend(Shackles::ClassMethods)
194
+ ::GuardRail.singleton_class.prepend(GuardRail::ClassMethods)
193
195
  end
194
196
  end
195
197
 
196
- initializer 'switchman.extend_controller', :after => "shackles.extend_ar" do
198
+ initializer 'switchman.extend_controller', :after => "guard_rail.extend_ar" do
197
199
  ::ActiveSupport.on_load(:action_controller) do
198
200
  require "switchman/action_controller/caching"
199
201
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'etc'
2
4
 
3
5
  module Switchman
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
4
  class NonExistentShardError < RuntimeError; end
3
5
  class ParallelShardExecError < RuntimeError; end
@@ -1,17 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
- module Shackles
4
+ module GuardRail
3
5
  module ClassMethods
4
6
  def self.prepended(klass)
5
7
  klass.send(:remove_method, :ensure_handler)
6
8
  end
7
9
 
8
10
  # drops the save_handler and ensure_handler calls from the vanilla
9
- # Shackles' implementation.
11
+ # GuardRail' implementation.
10
12
  def activate!(environment)
11
- environment ||= :master
13
+ environment ||= :primary
12
14
  activated_environments << environment
13
15
  old_environment = self.environment
14
- Thread.current[:shackles_environment] = environment
16
+ Thread.current[:guard_rail_environment] = environment
15
17
  old_environment
16
18
  end
17
19
 
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Switchman
2
- module Shackles
4
+ module GuardRail
3
5
  module Relation
4
6
  def exec_queries(*args)
5
7
  if self.lock_value
6
8
  db = Shard.current(shard_category).database_server
7
- if ::Shackles.environment != db.shackles_environment
8
- return db.unshackle { super }
9
+ if ::GuardRail.environment != db.guard_rail_environment
10
+ return db.unguard { super }
9
11
  end
10
12
  end
11
13
  super
@@ -15,8 +17,8 @@ module Switchman
15
17
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
16
18
  def #{method}(*args)
17
19
  db = Shard.current(shard_category).database_server
18
- if ::Shackles.environment != db.shackles_environment
19
- db.unshackle { super }
20
+ if ::GuardRail.environment != db.guard_rail_environment
21
+ db.unguard { super }
20
22
  else
21
23
  super
22
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'open4'
2
4
 
3
5
  # This fixes a bug with exception handling,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "switchman/test_helper"
2
4
 
3
5
  module Switchman
@@ -65,7 +67,7 @@ module Switchman
65
67
  (@@shard3.drop_database if @@shard3) rescue nil
66
68
  @@shard1 = @@shard2 = @@shard3 = nil
67
69
  Shard.delete_all
68
- Shard.default(true)
70
+ Shard.default(reload: true)
69
71
  next
70
72
  end
71
73
  end
@@ -73,7 +75,7 @@ module Switchman
73
75
  # in the db before then
74
76
  Shard.delete_all
75
77
  Switchman.cache.delete("default_shard")
76
- Shard.default(true)
78
+ Shard.default(reload: true)
77
79
  puts "Done!"
78
80
 
79
81
  at_exit do
@@ -102,7 +104,7 @@ module Switchman
102
104
  dup.id = @@default_shard.id
103
105
  dup.save!
104
106
  Switchman.cache.delete("default_shard")
105
- Shard.default(true)
107
+ Shard.default(reload: true)
106
108
  dup = @@shard1.dup
107
109
  dup.id = @@shard1.id
108
110
  dup.save!
@@ -122,7 +124,7 @@ module Switchman
122
124
  raise "Sharding did not set up correctly" if @@sharding_failed
123
125
  Shard.clear_cache
124
126
  if use_transactional_tests
125
- Shard.default(true)
127
+ Shard.default(reload: true)
126
128
  @shard1 = Shard.find(@shard1.id)
127
129
  @shard2 = Shard.find(@shard2.id)
128
130
  shards = [@shard2]
@@ -151,7 +153,7 @@ module Switchman
151
153
  klass.after(:all) do
152
154
  Shard.connection.update("TRUNCATE #{Shard.quoted_table_name} CASCADE")
153
155
  Switchman.cache.delete("default_shard")
154
- Shard.default(true)
156
+ Shard.default(reload: true)
155
157
  end
156
158
  end
157
159
  end