makara 0.4.1 → 0.5.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.
Files changed (88) hide show
  1. checksums.yaml +5 -5
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/CI.yml +88 -0
  4. data/.github/workflows/gem-publish-public.yml +36 -0
  5. data/.rspec +1 -1
  6. data/.rubocop.yml +15 -0
  7. data/.rubocop_todo.yml +670 -0
  8. data/CHANGELOG.md +69 -48
  9. data/Gemfile +1 -16
  10. data/README.md +8 -9
  11. data/Rakefile +1 -1
  12. data/gemfiles/activerecord_5.2.gemfile +8 -0
  13. data/gemfiles/activerecord_6.0.gemfile +8 -0
  14. data/gemfiles/activerecord_6.1.gemfile +8 -0
  15. data/gemfiles/activerecord_head.gemfile +6 -0
  16. data/lib/active_record/connection_adapters/jdbcmysql_makara_adapter.rb +4 -18
  17. data/lib/active_record/connection_adapters/jdbcpostgresql_makara_adapter.rb +4 -18
  18. data/lib/active_record/connection_adapters/makara_abstract_adapter.rb +107 -30
  19. data/lib/active_record/connection_adapters/makara_jdbcmysql_adapter.rb +4 -18
  20. data/lib/active_record/connection_adapters/makara_jdbcpostgresql_adapter.rb +4 -18
  21. data/lib/active_record/connection_adapters/makara_mysql2_adapter.rb +4 -20
  22. data/lib/active_record/connection_adapters/makara_postgis_adapter.rb +4 -19
  23. data/lib/active_record/connection_adapters/makara_postgresql_adapter.rb +4 -20
  24. data/lib/active_record/connection_adapters/mysql2_makara_adapter.rb +4 -20
  25. data/lib/active_record/connection_adapters/postgresql_makara_adapter.rb +4 -20
  26. data/lib/makara/cache.rb +0 -2
  27. data/lib/makara/config_parser.rb +7 -15
  28. data/lib/makara/connection_wrapper.rb +43 -22
  29. data/lib/makara/context.rb +1 -0
  30. data/lib/makara/cookie.rb +1 -0
  31. data/lib/makara/error_handler.rb +0 -9
  32. data/lib/makara/errors/all_connections_blacklisted.rb +0 -2
  33. data/lib/makara/errors/blacklist_connection.rb +0 -2
  34. data/lib/makara/errors/blacklisted_while_in_transaction.rb +12 -0
  35. data/lib/makara/errors/invalid_shard.rb +14 -0
  36. data/lib/makara/errors/makara_error.rb +0 -1
  37. data/lib/makara/errors/no_connections_available.rb +0 -2
  38. data/lib/makara/logging/logger.rb +0 -4
  39. data/lib/makara/logging/subscriber.rb +0 -2
  40. data/lib/makara/middleware.rb +1 -2
  41. data/lib/makara/pool.rb +49 -31
  42. data/lib/makara/proxy.rb +56 -30
  43. data/lib/makara/railtie.rb +0 -2
  44. data/lib/makara/strategies/abstract.rb +1 -0
  45. data/lib/makara/strategies/priority_failover.rb +2 -0
  46. data/lib/makara/strategies/round_robin.rb +1 -3
  47. data/lib/makara/strategies/shard_aware.rb +45 -0
  48. data/lib/makara/version.rb +1 -3
  49. data/lib/makara.rb +7 -6
  50. data/makara.gemspec +26 -3
  51. data/spec/active_record/connection_adapters/makara_abstract_adapter_error_handling_spec.rb +1 -6
  52. data/spec/active_record/connection_adapters/makara_abstract_adapter_spec.rb +0 -9
  53. data/spec/active_record/connection_adapters/makara_mysql2_adapter_spec.rb +9 -22
  54. data/spec/active_record/connection_adapters/makara_postgis_adapter_spec.rb +2 -10
  55. data/spec/active_record/connection_adapters/makara_postgresql_adapter_spec.rb +62 -18
  56. data/spec/cache_spec.rb +0 -1
  57. data/spec/config_parser_spec.rb +54 -56
  58. data/spec/connection_wrapper_spec.rb +1 -2
  59. data/spec/cookie_spec.rb +4 -4
  60. data/spec/middleware_spec.rb +2 -2
  61. data/spec/pool_spec.rb +25 -14
  62. data/spec/proxy_spec.rb +0 -4
  63. data/spec/spec_helper.rb +6 -1
  64. data/spec/strategies/priority_failover_spec.rb +3 -4
  65. data/spec/strategies/round_robin_spec.rb +4 -8
  66. data/spec/strategies/shard_aware_spec.rb +218 -0
  67. data/spec/support/deep_dup.rb +1 -1
  68. data/spec/support/helpers.rb +5 -5
  69. data/spec/support/mock_objects.rb +5 -4
  70. data/spec/support/mysql2_database.yml +2 -2
  71. data/spec/support/mysql2_database_with_custom_errors.yml +2 -2
  72. data/spec/support/pool_extensions.rb +0 -3
  73. data/spec/support/postgis_schema.rb +1 -1
  74. data/spec/support/postgresql_database.yml +0 -2
  75. data/spec/support/proxy_extensions.rb +1 -3
  76. data/spec/support/schema.rb +1 -1
  77. data/spec/support/user.rb +1 -2
  78. metadata +165 -20
  79. data/.travis.yml +0 -105
  80. data/gemfiles/ar-head.gemfile +0 -24
  81. data/gemfiles/ar30.gemfile +0 -36
  82. data/gemfiles/ar31.gemfile +0 -36
  83. data/gemfiles/ar32.gemfile +0 -36
  84. data/gemfiles/ar40.gemfile +0 -24
  85. data/gemfiles/ar41.gemfile +0 -24
  86. data/gemfiles/ar42.gemfile +0 -24
  87. data/gemfiles/ar50.gemfile +0 -24
  88. data/gemfiles/ar51.gemfile +0 -24
@@ -1,6 +1,5 @@
1
1
  module Makara
2
2
  module Logging
3
-
4
3
  module Subscriber
5
4
  IGNORE_PAYLOAD_NAMES = ["SCHEMA", "EXPLAIN"]
6
5
 
@@ -33,6 +32,5 @@ module Makara
33
32
  "[#{adapter._makara_name}]"
34
33
  end
35
34
  end
36
-
37
35
  end
38
36
  end
@@ -3,7 +3,6 @@ require 'rack'
3
3
  # Persists the Makara::Context across requests ensuring the same master pool is used on subsequent requests.
4
4
  module Makara
5
5
  class Middleware
6
-
7
6
  def initialize(app, cookie_options = {})
8
7
  @app = app
9
8
  @cookie_options = cookie_options
@@ -11,6 +10,7 @@ module Makara
11
10
 
12
11
  def call(env)
13
12
  return @app.call(env) if ignore_request?(env)
13
+
14
14
  set_current_context(env)
15
15
 
16
16
  status, headers, body = @app.call(env)
@@ -19,7 +19,6 @@ module Makara
19
19
  [status, headers, body]
20
20
  end
21
21
 
22
-
23
22
  protected
24
23
 
25
24
  def set_current_context(env)
data/lib/makara/pool.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  require 'active_support/core_ext/hash/keys'
2
+ require 'makara/strategies/shard_aware'
2
3
 
3
4
  # Wraps a collection of similar connections and chooses which one to use
4
5
  # Provides convenience methods for accessing underlying connections
5
6
 
6
7
  module Makara
7
8
  class Pool
8
-
9
9
  # there are cases when we understand the pool is busted and we essentially want to skip
10
10
  # all execution
11
11
  attr_accessor :disabled
@@ -13,6 +13,8 @@ module Makara
13
13
  attr_reader :role
14
14
  attr_reader :connections
15
15
  attr_reader :strategy
16
+ attr_reader :shard_strategy_class
17
+ attr_reader :default_shard
16
18
 
17
19
  def initialize(role, proxy)
18
20
  @role = role
@@ -20,10 +22,15 @@ module Makara
20
22
  @connections = []
21
23
  @blacklist_errors = []
22
24
  @disabled = false
23
- @strategy = proxy.strategy_for(role)
25
+ if proxy.shard_aware_for(role)
26
+ @strategy = Makara::Strategies::ShardAware.new(self)
27
+ @shard_strategy_class = proxy.strategy_class_for(proxy.strategy_name_for(role))
28
+ @default_shard = proxy.default_shard_for(role)
29
+ else
30
+ @strategy = proxy.strategy_for(role)
31
+ end
24
32
  end
25
33
 
26
-
27
34
  def completely_blacklisted?
28
35
  @connections.each do |connection|
29
36
  return false unless connection._makara_blacklisted?
@@ -31,7 +38,6 @@ module Makara
31
38
  true
32
39
  end
33
40
 
34
-
35
41
  # Add a connection to this pool, wrapping the connection with a Makara::ConnectionWrapper
36
42
  def add(config)
37
43
  config[:name] ||= "#{@role}/#{@connections.length + 1}"
@@ -61,6 +67,7 @@ module Makara
61
67
 
62
68
  @connections.each do |con|
63
69
  next if con._makara_blacklisted?
70
+
64
71
  begin
65
72
  ret = @proxy.error_handler.handle(con) do
66
73
  if block
@@ -91,52 +98,63 @@ module Makara
91
98
  # Provide a connection that is not blacklisted and connected. Handle any errors
92
99
  # that may occur within the block.
93
100
  def provide
94
- provided_connection = self.next
101
+ attempt = 0
102
+ begin
103
+ provided_connection = self.next
95
104
 
96
- # nil implies that it's blacklisted
97
- if provided_connection
105
+ # nil implies that it's blacklisted
106
+ if provided_connection
98
107
 
99
- value = @proxy.error_handler.handle(provided_connection) do
100
- yield provided_connection
101
- end
108
+ value = @proxy.error_handler.handle(provided_connection) do
109
+ yield provided_connection
110
+ end
102
111
 
103
- @blacklist_errors = []
112
+ @blacklist_errors = []
104
113
 
105
- value
114
+ value
106
115
 
107
- # if we've made any connections within this pool, we should report the blackout.
108
- elsif connection_made?
109
- err = Makara::Errors::AllConnectionsBlacklisted.new(self, @blacklist_errors)
110
- @blacklist_errors = []
111
- raise err
112
- else
113
- raise Makara::Errors::NoConnectionsAvailable.new(@role) unless @disabled
114
- end
116
+ # if we've made any connections within this pool, we should report the blackout.
117
+ elsif connection_made?
118
+ err = Makara::Errors::AllConnectionsBlacklisted.new(self, @blacklist_errors)
119
+ @blacklist_errors = []
120
+ raise err
121
+ else
122
+ raise Makara::Errors::NoConnectionsAvailable.new(@role) unless @disabled
123
+ end
115
124
 
116
- # when a connection causes a blacklist error within the provided block, we blacklist it then retry
117
- rescue Makara::Errors::BlacklistConnection => e
118
- @blacklist_errors.insert(0, e)
119
- provided_connection._makara_blacklist!
120
- retry
125
+ # when a connection causes a blacklist error within the provided block, we blacklist it then retry
126
+ rescue Makara::Errors::BlacklistConnection => e
127
+ @blacklist_errors.insert(0, e)
128
+ in_transaction = self.role == "master" && provided_connection._makara_in_transaction?
129
+ provided_connection._makara_blacklist!
130
+ raise Makara::Errors::BlacklistedWhileInTransaction.new(@role) if in_transaction
131
+
132
+ attempt += 1
133
+ if attempt < @connections.length
134
+ retry
135
+ elsif connection_made?
136
+ err = Makara::Errors::AllConnectionsBlacklisted.new(self, @blacklist_errors)
137
+ @blacklist_errors = []
138
+ raise err
139
+ else
140
+ raise Makara::Errors::NoConnectionsAvailable.new(@role) unless @disabled
141
+ end
142
+ end
121
143
  end
122
144
 
123
-
124
-
125
145
  protected
126
146
 
127
-
128
147
  # have we connected to any of the underlying connections.
129
148
  def connection_made?
130
149
  @connections.any?(&:_makara_connected?)
131
150
  end
132
151
 
133
-
134
152
  # Get the next non-blacklisted connection. If the proxy is setup
135
153
  # to be sticky, provide back the current connection assuming it is
136
154
  # not blacklisted.
137
155
  def next
138
- if @proxy.sticky && @strategy.current
139
- @strategy.current
156
+ if @proxy.sticky && (curr = @strategy.current)
157
+ curr
140
158
  else
141
159
  @strategy.next
142
160
  end
data/lib/makara/proxy.rb CHANGED
@@ -11,11 +11,11 @@ require 'active_support/core_ext/string/inflections'
11
11
 
12
12
  module Makara
13
13
  class Proxy < ::SimpleDelegator
14
-
15
14
  METHOD_MISSING_SKIP = [ :byebug, :puts ]
16
15
 
17
- class_attribute :hijack_methods
16
+ class_attribute :hijack_methods, :control_methods
18
17
  self.hijack_methods = []
18
+ self.control_methods = []
19
19
 
20
20
  class << self
21
21
  def hijack_method(*method_names)
@@ -23,27 +23,44 @@ module Makara
23
23
  self.hijack_methods |= method_names
24
24
 
25
25
  method_names.each do |method_name|
26
- define_method method_name do |*args, &block|
26
+ define_method(method_name) do |*args, &block|
27
27
  appropriate_connection(method_name, args) do |con|
28
28
  con.send(method_name, *args, &block)
29
29
  end
30
30
  end
31
+
32
+ ruby2_keywords method_name if Module.private_method_defined?(:ruby2_keywords)
31
33
  end
32
34
  end
33
35
 
34
36
  def send_to_all(*method_names)
35
37
  method_names.each do |method_name|
36
- define_method method_name do |*args|
37
- send_to_all method_name, *args
38
+ define_method(method_name) do |*args|
39
+ send_to_all(method_name, *args)
38
40
  end
41
+
42
+ ruby2_keywords method_name if Module.private_method_defined?(:ruby2_keywords)
39
43
  end
40
44
  end
41
- end
42
45
 
46
+ def control_method(*method_names)
47
+ self.control_methods = self.control_methods || []
48
+ self.control_methods |= method_names
49
+
50
+ method_names.each do |method_name|
51
+ define_method(method_name) do |*args, &block|
52
+ control&.send(method_name, *args, &block)
53
+ end
54
+
55
+ ruby2_keywords method_name if Module.private_method_defined?(:ruby2_keywords)
56
+ end
57
+ end
58
+ end
43
59
 
44
60
  attr_reader :error_handler
45
61
  attr_reader :sticky
46
62
  attr_reader :config_parser
63
+ attr_reader :control
47
64
 
48
65
  def initialize(config)
49
66
  @config = config.symbolize_keys
@@ -84,6 +101,14 @@ module Makara
84
101
  @config_parser.makara_config["#{role}_strategy".to_sym]
85
102
  end
86
103
 
104
+ def shard_aware_for(role)
105
+ @config_parser.makara_config["#{role}_shard_aware".to_sym]
106
+ end
107
+
108
+ def default_shard_for(role)
109
+ @config_parser.makara_config["#{role}_default_shard".to_sym]
110
+ end
111
+
87
112
  def strategy_class_for(strategy_name)
88
113
  case strategy_name
89
114
  when 'round_robin', 'roundrobin', nil, ''
@@ -97,27 +122,25 @@ module Makara
97
122
 
98
123
  def method_missing(m, *args, &block)
99
124
  if METHOD_MISSING_SKIP.include?(m)
100
- return super(m, *args, &block)
125
+ return super
101
126
  end
102
127
 
103
128
  any_connection do |con|
104
- if con.respond_to?(m)
105
- con.public_send(m, *args, &block)
106
- elsif con.respond_to?(m, true)
107
- con.__send__(m, *args, &block)
129
+ if con.respond_to?(m, true)
130
+ con.send(m, *args, &block)
108
131
  else
109
- super(m, *args, &block)
132
+ super
110
133
  end
111
134
  end
112
135
  end
113
136
 
114
- class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
115
- def respond_to#{RUBY_VERSION.to_s =~ /^1.8/ ? nil : '_missing'}?(m, include_private = false)
116
- any_connection do |con|
117
- con._makara_connection.respond_to?(m, true)
118
- end
137
+ ruby2_keywords :method_missing if Module.private_method_defined?(:ruby2_keywords)
138
+
139
+ def respond_to_missing?(m, include_private = false)
140
+ any_connection do |con|
141
+ con._makara_connection.respond_to?(m, true)
119
142
  end
120
- RUBY_EVAL
143
+ end
121
144
 
122
145
  def graceful_connection_for(config)
123
146
  fake_wrapper = Makara::ConnectionWrapper.new(self, nil, config)
@@ -138,18 +161,25 @@ module Makara
138
161
 
139
162
  protected
140
163
 
141
-
142
164
  def send_to_all(method_name, *args)
143
165
  # slave pool must run first to allow for slave-->master failover without running operations on master twice.
144
166
  handling_an_all_execution(method_name) do
145
- @slave_pool.send_to_all method_name, *args
146
- @master_pool.send_to_all method_name, *args
167
+ @slave_pool.send_to_all(method_name, *args)
168
+ @master_pool.send_to_all(method_name, *args)
147
169
  end
148
170
  end
149
171
 
172
+ ruby2_keywords :send_to_all if Module.private_method_defined?(:ruby2_keywords)
173
+
150
174
  def any_connection
151
- @master_pool.provide do |con|
152
- yield con
175
+ if @master_pool.disabled
176
+ @slave_pool.provide do |con|
177
+ yield con
178
+ end
179
+ else
180
+ @master_pool.provide do |con|
181
+ yield con
182
+ end
153
183
  end
154
184
  rescue ::Makara::Errors::AllConnectionsBlacklisted, ::Makara::Errors::NoConnectionsAvailable
155
185
  begin
@@ -175,14 +205,11 @@ module Makara
175
205
  end
176
206
  end
177
207
 
178
-
179
208
  # master or slave
180
209
  def appropriate_pool(method_name, args)
181
-
182
210
  # for testing purposes
183
211
  pool = _appropriate_pool(method_name, args)
184
212
  yield pool
185
-
186
213
  rescue ::Makara::Errors::AllConnectionsBlacklisted, ::Makara::Errors::NoConnectionsAvailable => e
187
214
  if pool == @master_pool
188
215
  @master_pool.connections.each(&:_makara_whitelist!)
@@ -241,7 +268,6 @@ module Makara
241
268
  @hijacked = false
242
269
  end
243
270
 
244
-
245
271
  def stuck_to_master?
246
272
  sticky? && Makara::Context.stuck?(@id)
247
273
  end
@@ -286,18 +312,18 @@ module Makara
286
312
  yield
287
313
  rescue ::Makara::Errors::NoConnectionsAvailable => e
288
314
  if e.role == 'master'
289
- Kernel.raise ::Makara::Errors::NoConnectionsAvailable.new('master and slave')
315
+ # this means slave connections are good.
316
+ return
290
317
  end
318
+
291
319
  @slave_pool.disabled = true
292
320
  yield
293
321
  ensure
294
322
  @slave_pool.disabled = false
295
323
  end
296
324
 
297
-
298
325
  def connection_for(config)
299
326
  Kernel.raise NotImplementedError
300
327
  end
301
-
302
328
  end
303
329
  end
@@ -1,9 +1,7 @@
1
1
  module Makara
2
2
  class Railtie < ::Rails::Railtie
3
-
4
3
  initializer "makara.configure_rails_initialization" do |app|
5
4
  app.middleware.use Makara::Middleware
6
5
  end
7
-
8
6
  end
9
7
  end
@@ -2,6 +2,7 @@ module Makara
2
2
  module Strategies
3
3
  class Abstract
4
4
  attr_reader :pool
5
+
5
6
  def initialize(pool)
6
7
  @pool = pool
7
8
  init
@@ -27,6 +27,7 @@ module Makara
27
27
  @weighted_connections.each_with_index do |con, index|
28
28
  check = safe_value(index)
29
29
  next unless check
30
+
30
31
  @current_idx = index
31
32
  return check
32
33
  end
@@ -41,6 +42,7 @@ module Makara
41
42
  con = @weighted_connections[idx]
42
43
  return nil unless con
43
44
  return nil if con._makara_blacklisted?
45
+
44
46
  con
45
47
  end
46
48
  end
@@ -26,8 +26,8 @@ module Makara
26
26
  return safe_value(0, true) if single_one?
27
27
 
28
28
  idx = @current_idx
29
- begin
30
29
 
30
+ begin
31
31
  idx = next_index(idx)
32
32
 
33
33
  # if we've looped all the way around, return our safe value
@@ -48,7 +48,6 @@ module Makara
48
48
  idx
49
49
  end
50
50
 
51
-
52
51
  # return the connection if it's not blacklisted
53
52
  # otherwise return nil
54
53
  # optionally, store the position and context we're returning
@@ -64,7 +63,6 @@ module Makara
64
63
  con
65
64
  end
66
65
 
67
-
68
66
  # stub in test mode to ensure consistency
69
67
  def should_shuffle?
70
68
  true
@@ -0,0 +1,45 @@
1
+ require 'makara/errors/invalid_shard'
2
+
3
+ module Makara
4
+ module Strategies
5
+ class ShardAware < ::Makara::Strategies::Abstract
6
+ def init
7
+ @shards = {}
8
+ @default_shard = pool.default_shard
9
+ end
10
+
11
+ def connection_added(wrapper)
12
+ id = wrapper._makara_shard_id
13
+ shard_strategy(id).connection_added(wrapper)
14
+ end
15
+
16
+ def shard_strategy(shard_id)
17
+ id = shard_id
18
+ shard_strategy = @shards[id]
19
+ unless shard_strategy
20
+ shard_strategy = pool.shard_strategy_class.new(pool)
21
+ @shards[id] = shard_strategy
22
+ end
23
+ shard_strategy
24
+ end
25
+
26
+ def current
27
+ id = shard_id
28
+ raise Makara::Errors::InvalidShard.new(pool.role, id) unless id && @shards[id]
29
+
30
+ @shards[id].current
31
+ end
32
+
33
+ def next
34
+ id = shard_id
35
+ raise Makara::Errors::InvalidShard.new(pool.role, id) unless id && @shards[id]
36
+
37
+ @shards[id].next
38
+ end
39
+
40
+ def shard_id
41
+ Thread.current['makara_shard_id'] || pool.default_shard
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,15 +1,13 @@
1
1
  module Makara
2
2
  module VERSION
3
-
4
3
  MAJOR = 0
5
- MINOR = 4
4
+ MINOR = 5
6
5
  PATCH = 1
7
6
  PRE = nil
8
7
 
9
8
  def self.to_s
10
9
  [MAJOR, MINOR, PATCH, PRE].compact.join('.')
11
10
  end
12
-
13
11
  end unless defined?(::Makara::VERSION)
14
12
  ::Makara::VERSION
15
13
  end
data/lib/makara.rb CHANGED
@@ -2,7 +2,6 @@ require 'active_support'
2
2
  require 'makara/version'
3
3
  require 'makara/railtie' if defined?(Rails)
4
4
  module Makara
5
-
6
5
  autoload :Cache, 'makara/cache'
7
6
  autoload :ConfigParser, 'makara/config_parser'
8
7
  autoload :ConnectionWrapper, 'makara/connection_wrapper'
@@ -14,10 +13,12 @@ module Makara
14
13
  autoload :Proxy, 'makara/proxy'
15
14
 
16
15
  module Errors
17
- autoload :MakaraError, 'makara/errors/makara_error'
18
- autoload :AllConnectionsBlacklisted, 'makara/errors/all_connections_blacklisted'
19
- autoload :BlacklistConnection, 'makara/errors/blacklist_connection'
20
- autoload :NoConnectionsAvailable, 'makara/errors/no_connections_available'
16
+ autoload :MakaraError, 'makara/errors/makara_error'
17
+ autoload :AllConnectionsBlacklisted, 'makara/errors/all_connections_blacklisted'
18
+ autoload :BlacklistConnection, 'makara/errors/blacklist_connection'
19
+ autoload :NoConnectionsAvailable, 'makara/errors/no_connections_available'
20
+ autoload :BlacklistedWhileInTransaction, 'makara/errors/blacklisted_while_in_transaction'
21
+ autoload :InvalidShard, 'makara/errors/invalid_shard'
21
22
  end
22
23
 
23
24
  module Logging
@@ -29,8 +30,8 @@ module Makara
29
30
  autoload :Abstract, 'makara/strategies/abstract'
30
31
  autoload :RoundRobin, 'makara/strategies/round_robin'
31
32
  autoload :PriorityFailover, 'makara/strategies/priority_failover'
33
+ autoload :ShardAware, 'makara/strategies/shard_aware'
32
34
  end
33
-
34
35
  end
35
36
 
36
37
  ActiveSupport.on_load(:active_record) do
data/makara.gemspec CHANGED
@@ -1,4 +1,3 @@
1
- # -*- encoding: utf-8 -*-
2
1
  require File.expand_path('../lib/makara/version', __FILE__)
3
2
 
4
3
  Gem::Specification.new do |gem|
@@ -6,7 +5,11 @@ Gem::Specification.new do |gem|
6
5
  gem.email = ["mike@mikeonrails.com"]
7
6
  gem.description = %q{Read-write split your DB yo}
8
7
  gem.summary = %q{Read-write split your DB yo}
9
- gem.homepage = ""
8
+ gem.homepage = "https://github.com/instacart/makara"
9
+ gem.licenses = ['MIT']
10
+ gem.metadata = {
11
+ "source_code_uri" => 'https://github.com/instacart/makara'
12
+ }
10
13
 
11
14
  gem.files = `git ls-files`.split($\)
12
15
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -15,5 +18,25 @@ Gem::Specification.new do |gem|
15
18
  gem.require_paths = ["lib"]
16
19
  gem.version = Makara::VERSION
17
20
 
18
- gem.add_dependency 'activerecord', '>= 3.0.0'
21
+ gem.required_ruby_version = ">= 2.5.0"
22
+
23
+ gem.add_dependency "activerecord", ">= 5.2.0"
24
+
25
+ gem.add_development_dependency "rack"
26
+ gem.add_development_dependency "rake", "~> 13.0"
27
+ gem.add_development_dependency "rspec", "~> 3.9"
28
+ gem.add_development_dependency "timecop"
29
+ gem.add_development_dependency "rubocop", "~> 1.9.1"
30
+
31
+ if RUBY_ENGINE == "jruby"
32
+ gem.add_development_dependency "activerecord-jdbcmysql-adapter"
33
+ gem.add_development_dependency "activerecord-jdbcpostgresql-adapter"
34
+ gem.add_development_dependency "ruby-debug"
35
+ else
36
+ gem.add_development_dependency "activerecord-postgis-adapter"
37
+ gem.add_development_dependency "pry-byebug"
38
+ gem.add_development_dependency "mysql2"
39
+ gem.add_development_dependency "pg"
40
+ gem.add_development_dependency "rgeo"
41
+ end
19
42
  end
@@ -2,7 +2,6 @@ require 'spec_helper'
2
2
  require 'active_record/connection_adapters/makara_abstract_adapter'
3
3
 
4
4
  describe ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter::ErrorHandler do
5
-
6
5
  let(:handler){ described_class.new }
7
6
  let(:proxy) { FakeAdapter.new(config(1,1)) }
8
7
  let(:connection){ proxy.master_pool.connections.first }
@@ -60,9 +59,8 @@ describe ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter::ErrorHandler d
60
59
  end
61
60
 
62
61
  describe 'custom errors' do
63
-
64
62
  let(:config_path) { File.join(File.expand_path('../../../', __FILE__), 'support', 'mysql2_database_with_custom_errors.yml') }
65
- let(:config) { YAML.load_file(config_path)['test'] }
63
+ let(:config) { YAML.load(ERB.new(File.read(config_path)).result)['test'] }
66
64
  let(:handler){ described_class.new }
67
65
  let(:proxy) { FakeAdapter.new(config) }
68
66
  let(:connection){ proxy.master_pool.connections.first }
@@ -85,8 +83,5 @@ describe ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter::ErrorHandler d
85
83
  end
86
84
  }.to raise_error(Makara::Errors::BlacklistConnection)
87
85
  end
88
-
89
86
  end
90
-
91
-
92
87
  end
@@ -2,7 +2,6 @@ require 'spec_helper'
2
2
  require 'active_record/connection_adapters/makara_abstract_adapter'
3
3
 
4
4
  describe ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter do
5
-
6
5
  let(:klass){ FakeAdapter }
7
6
 
8
7
  {
@@ -38,15 +37,12 @@ describe ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter do
38
37
  'select pg_advisory_lock(12345)' => true,
39
38
  'select pg_advisory_unlock(12345)' => true
40
39
  }.each do |sql, should_go_to_master|
41
-
42
40
  it "determines that \"#{sql}\" #{should_go_to_master ? 'requires' : 'does not require'} master" do
43
41
  proxy = klass.new(config(1,1))
44
42
  expect(proxy.master_for?(sql)).to eq(should_go_to_master)
45
43
  end
46
-
47
44
  end
48
45
 
49
-
50
46
  {
51
47
  "SET @@things" => true,
52
48
  "INSERT INTO wisdom ('The truth will set you free.')" => false,
@@ -61,7 +57,6 @@ describe ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter do
61
57
  max_treats IS NULL
62
58
  } => false
63
59
  }.each do |sql, should_send_to_all_connections|
64
-
65
60
  it "determines that \"#{sql}\" #{should_send_to_all_connections ? 'should' : 'should not'} be sent to all underlying connections" do
66
61
  proxy = klass.new(config(1,1))
67
62
  proxy.master_pool.connections.each{|con| expect(con).to receive(:execute).with(sql).once}
@@ -75,7 +70,6 @@ describe ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter do
75
70
 
76
71
  proxy.execute(sql)
77
72
  end
78
-
79
73
  end
80
74
 
81
75
  {
@@ -108,12 +102,9 @@ describe ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter do
108
102
  max_treats IS NULL
109
103
  } => true
110
104
  }.each do |sql,should_stick|
111
-
112
105
  it "should #{should_stick ? 'stick' : 'not stick'} to master if handling sql like \"#{sql}\"" do
113
106
  proxy = klass.new(config(0,0))
114
107
  expect(proxy.would_stick?(sql)).to eq(should_stick)
115
108
  end
116
-
117
109
  end
118
-
119
110
  end