makara 0.5.0 → 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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +11 -0
  3. data/.github/workflows/CI.yml +88 -0
  4. data/.rspec +1 -1
  5. data/.rubocop.yml +15 -0
  6. data/.rubocop_todo.yml +670 -0
  7. data/CHANGELOG.md +14 -6
  8. data/Gemfile +1 -16
  9. data/README.md +2 -1
  10. data/Rakefile +1 -1
  11. data/gemfiles/activerecord_5.2.gemfile +8 -0
  12. data/gemfiles/activerecord_6.0.gemfile +8 -0
  13. data/gemfiles/activerecord_6.1.gemfile +8 -0
  14. data/gemfiles/activerecord_head.gemfile +6 -0
  15. data/lib/active_record/connection_adapters/jdbcmysql_makara_adapter.rb +4 -18
  16. data/lib/active_record/connection_adapters/jdbcpostgresql_makara_adapter.rb +4 -18
  17. data/lib/active_record/connection_adapters/makara_abstract_adapter.rb +3 -31
  18. data/lib/active_record/connection_adapters/makara_jdbcmysql_adapter.rb +4 -18
  19. data/lib/active_record/connection_adapters/makara_jdbcpostgresql_adapter.rb +4 -18
  20. data/lib/active_record/connection_adapters/makara_mysql2_adapter.rb +4 -20
  21. data/lib/active_record/connection_adapters/makara_postgis_adapter.rb +4 -19
  22. data/lib/active_record/connection_adapters/makara_postgresql_adapter.rb +4 -20
  23. data/lib/active_record/connection_adapters/mysql2_makara_adapter.rb +4 -20
  24. data/lib/active_record/connection_adapters/postgresql_makara_adapter.rb +4 -20
  25. data/lib/makara.rb +0 -2
  26. data/lib/makara/cache.rb +0 -2
  27. data/lib/makara/config_parser.rb +5 -14
  28. data/lib/makara/connection_wrapper.rb +24 -27
  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 +0 -2
  35. data/lib/makara/errors/invalid_shard.rb +1 -3
  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 +2 -7
  42. data/lib/makara/proxy.rb +25 -27
  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 +0 -2
  48. data/lib/makara/version.rb +1 -3
  49. data/makara.gemspec +24 -5
  50. data/spec/active_record/connection_adapters/makara_abstract_adapter_error_handling_spec.rb +1 -6
  51. data/spec/active_record/connection_adapters/makara_abstract_adapter_spec.rb +0 -9
  52. data/spec/active_record/connection_adapters/makara_mysql2_adapter_spec.rb +9 -22
  53. data/spec/active_record/connection_adapters/makara_postgis_adapter_spec.rb +2 -10
  54. data/spec/active_record/connection_adapters/makara_postgresql_adapter_spec.rb +7 -20
  55. data/spec/cache_spec.rb +0 -1
  56. data/spec/config_parser_spec.rb +54 -56
  57. data/spec/connection_wrapper_spec.rb +1 -2
  58. data/spec/cookie_spec.rb +1 -1
  59. data/spec/middleware_spec.rb +1 -1
  60. data/spec/pool_spec.rb +3 -16
  61. data/spec/proxy_spec.rb +0 -4
  62. data/spec/spec_helper.rb +5 -1
  63. data/spec/strategies/priority_failover_spec.rb +3 -4
  64. data/spec/strategies/round_robin_spec.rb +4 -8
  65. data/spec/strategies/shard_aware_spec.rb +4 -5
  66. data/spec/support/deep_dup.rb +1 -1
  67. data/spec/support/helpers.rb +5 -5
  68. data/spec/support/mock_objects.rb +1 -4
  69. data/spec/support/mysql2_database.yml +2 -2
  70. data/spec/support/mysql2_database_with_custom_errors.yml +2 -2
  71. data/spec/support/pool_extensions.rb +0 -3
  72. data/spec/support/postgis_schema.rb +1 -1
  73. data/spec/support/postgresql_database.yml +0 -2
  74. data/spec/support/proxy_extensions.rb +1 -3
  75. data/spec/support/schema.rb +1 -1
  76. data/spec/support/user.rb +1 -2
  77. metadata +156 -20
  78. data/.travis.yml +0 -131
  79. data/gemfiles/ar-head.gemfile +0 -24
  80. data/gemfiles/ar30.gemfile +0 -36
  81. data/gemfiles/ar31.gemfile +0 -36
  82. data/gemfiles/ar32.gemfile +0 -36
  83. data/gemfiles/ar40.gemfile +0 -24
  84. data/gemfiles/ar41.gemfile +0 -24
  85. data/gemfiles/ar42.gemfile +0 -24
  86. data/gemfiles/ar50.gemfile +0 -24
  87. data/gemfiles/ar51.gemfile +0 -24
  88. data/gemfiles/ar52.gemfile +0 -24
  89. data/gemfiles/ar60.gemfile +0 -24
@@ -1,32 +1,17 @@
1
1
  require 'active_record/connection_adapters/makara_abstract_adapter'
2
2
  require 'active_record/connection_adapters/postgresql_adapter'
3
3
 
4
- if ActiveRecord::VERSION::MAJOR >= 4
5
-
6
- module ActiveRecord
7
- module ConnectionHandling
8
- def makara_postgresql_connection(config)
9
- ActiveRecord::ConnectionAdapters::MakaraPostgreSQLAdapter.new(config)
10
- end
11
- end
12
- end
13
-
14
- else
15
-
16
- module ActiveRecord
17
- class Base
18
- def self.makara_postgresql_connection(config)
19
- ActiveRecord::ConnectionAdapters::MakaraPostgreSQLAdapter.new(config)
20
- end
4
+ module ActiveRecord
5
+ module ConnectionHandling
6
+ def makara_postgresql_connection(config)
7
+ ActiveRecord::ConnectionAdapters::MakaraPostgreSQLAdapter.new(config)
21
8
  end
22
9
  end
23
-
24
10
  end
25
11
 
26
12
  module ActiveRecord
27
13
  module ConnectionAdapters
28
14
  class MakaraPostgreSQLAdapter < ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter
29
-
30
15
  class << self
31
16
  def visitor_for(*args)
32
17
  ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.visitor_for(*args)
@@ -38,7 +23,6 @@ module ActiveRecord
38
23
  def active_record_connection_for(config)
39
24
  ::ActiveRecord::Base.postgresql_connection(config)
40
25
  end
41
-
42
26
  end
43
27
  end
44
28
  end
@@ -1,32 +1,17 @@
1
1
  require 'active_record/connection_adapters/makara_abstract_adapter'
2
2
  require 'active_record/connection_adapters/mysql2_adapter'
3
3
 
4
- if ActiveRecord::VERSION::MAJOR >= 4
5
-
6
- module ActiveRecord
7
- module ConnectionHandling
8
- def mysql2_makara_connection(config)
9
- ActiveRecord::ConnectionAdapters::MakaraMysql2Adapter.new(config)
10
- end
11
- end
12
- end
13
-
14
- else
15
-
16
- module ActiveRecord
17
- class Base
18
- def self.mysql2_makara_connection(config)
19
- ActiveRecord::ConnectionAdapters::MakaraMysql2Adapter.new(config)
20
- end
4
+ module ActiveRecord
5
+ module ConnectionHandling
6
+ def mysql2_makara_connection(config)
7
+ ActiveRecord::ConnectionAdapters::MakaraMysql2Adapter.new(config)
21
8
  end
22
9
  end
23
-
24
10
  end
25
11
 
26
12
  module ActiveRecord
27
13
  module ConnectionAdapters
28
14
  class MakaraMysql2Adapter < ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter
29
-
30
15
  class << self
31
16
  def visitor_for(*args)
32
17
  ActiveRecord::ConnectionAdapters::Mysql2Adapter.visitor_for(*args)
@@ -38,7 +23,6 @@ module ActiveRecord
38
23
  def active_record_connection_for(config)
39
24
  ::ActiveRecord::Base.mysql2_connection(config)
40
25
  end
41
-
42
26
  end
43
27
  end
44
28
  end
@@ -1,32 +1,17 @@
1
1
  require 'active_record/connection_adapters/makara_abstract_adapter'
2
2
  require 'active_record/connection_adapters/postgresql_adapter'
3
3
 
4
- if ActiveRecord::VERSION::MAJOR >= 4
5
-
6
- module ActiveRecord
7
- module ConnectionHandling
8
- def postgresql_makara_connection(config)
9
- ActiveRecord::ConnectionAdapters::MakaraPostgreSQLAdapter.new(config)
10
- end
11
- end
12
- end
13
-
14
- else
15
-
16
- module ActiveRecord
17
- class Base
18
- def self.postgresql_makara_connection(config)
19
- ActiveRecord::ConnectionAdapters::MakaraPostgreSQLAdapter.new(config)
20
- end
4
+ module ActiveRecord
5
+ module ConnectionHandling
6
+ def postgresql_makara_connection(config)
7
+ ActiveRecord::ConnectionAdapters::MakaraPostgreSQLAdapter.new(config)
21
8
  end
22
9
  end
23
-
24
10
  end
25
11
 
26
12
  module ActiveRecord
27
13
  module ConnectionAdapters
28
14
  class MakaraPostgreSQLAdapter < ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter
29
-
30
15
  class << self
31
16
  def visitor_for(*args)
32
17
  ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.visitor_for(*args)
@@ -38,7 +23,6 @@ module ActiveRecord
38
23
  def active_record_connection_for(config)
39
24
  ::ActiveRecord::Base.postgresql_connection(config)
40
25
  end
41
-
42
26
  end
43
27
  end
44
28
  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'
@@ -33,7 +32,6 @@ module Makara
33
32
  autoload :PriorityFailover, 'makara/strategies/priority_failover'
34
33
  autoload :ShardAware, 'makara/strategies/shard_aware'
35
34
  end
36
-
37
35
  end
38
36
 
39
37
  ActiveSupport.on_load(:active_record) do
data/lib/makara/cache.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  module Makara
2
2
  module Cache
3
-
4
3
  class << self
5
-
6
4
  def store=(store)
7
5
  Makara::Logging::Logger.log deprecation_warning, :warn
8
6
  end
@@ -20,11 +20,10 @@ require 'cgi'
20
20
 
21
21
  module Makara
22
22
  class ConfigParser
23
-
24
23
  DEFAULTS = {
25
- :master_ttl => 5,
26
- :blacklist_duration => 30,
27
- :sticky => true
24
+ master_ttl: 5,
25
+ blacklist_duration: 30,
26
+ sticky: true
28
27
  }
29
28
 
30
29
  # ConnectionUrlResolver is borrowed from Rails 4-2 since its location and implementation
@@ -33,7 +32,6 @@ module Makara
33
32
  #
34
33
  # Expands a connection string into a hash.
35
34
  class ConnectionUrlResolver # :nodoc:
36
-
37
35
  # == Example
38
36
  #
39
37
  # url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000"
@@ -50,6 +48,7 @@ module Makara
50
48
  # }
51
49
  def initialize(url)
52
50
  raise "Database URL cannot be empty" if url.blank?
51
+
53
52
  @uri = URI.parse(url)
54
53
  @adapter = @uri.scheme.tr('-', '_')
55
54
  @adapter = "postgresql" if @adapter == "postgres"
@@ -131,6 +130,7 @@ module Makara
131
130
  Makara::Logging::Logger.log "Please rename DATABASE_URL to use in the database.yml", :warn
132
131
  end
133
132
  return config unless config.key?(:url)
133
+
134
134
  url = config[:url]
135
135
  url_config = ConnectionUrlResolver.new(url).to_hash
136
136
  url_config = url_config.symbolize_keys
@@ -148,7 +148,6 @@ module Makara
148
148
  @id = sanitize_id(@makara_config[:id])
149
149
  end
150
150
 
151
-
152
151
  def id
153
152
  @id ||= begin
154
153
  sorted = recursive_sort(@config)
@@ -156,24 +155,20 @@ module Makara
156
155
  end
157
156
  end
158
157
 
159
-
160
158
  def master_configs
161
159
  all_configs
162
160
  .select { |config| config[:role] == 'master' }
163
161
  .map { |config| config.except(:role) }
164
162
  end
165
163
 
166
-
167
164
  def slave_configs
168
165
  all_configs
169
166
  .reject { |config| config[:role] == 'master' }
170
167
  .map { |config| config.except(:role) }
171
168
  end
172
169
 
173
-
174
170
  protected
175
171
 
176
-
177
172
  def all_configs
178
173
  @makara_config[:connections].map do |connection|
179
174
  base_config.merge(makara_config.except(:connections))
@@ -181,12 +176,10 @@ module Makara
181
176
  end
182
177
  end
183
178
 
184
-
185
179
  def base_config
186
180
  @base_config ||= DEFAULTS.merge(@config).except(:makara)
187
181
  end
188
182
 
189
-
190
183
  def recursive_sort(thing)
191
184
  return thing.to_s unless thing.include?(Enumerable)
192
185
 
@@ -195,10 +188,8 @@ module Makara
195
188
  end
196
189
 
197
190
  thing.sort_by(&:to_s)
198
-
199
191
  end
200
192
 
201
-
202
193
  def sanitize_id(id)
203
194
  return if id.nil? || id.empty?
204
195
 
@@ -7,7 +7,6 @@ require 'active_support/core_ext/hash/keys'
7
7
 
8
8
  module Makara
9
9
  class ConnectionWrapper
10
-
11
10
  attr_accessor :initial_error, :config
12
11
 
13
12
  # invalid queries caused by connections switching that needs to be replaced
@@ -16,7 +15,7 @@ module Makara
16
15
  def initialize(proxy, connection, config)
17
16
  @config = config.symbolize_keys
18
17
  @connection = connection
19
- @proxy = proxy
18
+ @proxy = proxy
20
19
 
21
20
  if connection.nil?
22
21
  _makara_blacklist!
@@ -45,7 +44,7 @@ module Makara
45
44
  end
46
45
 
47
46
  def _makara_in_transaction?
48
- @connection && @connection.open_transactions > 0 ? true : false
47
+ @connection && @connection.open_transactions > 0
49
48
  end
50
49
 
51
50
  # blacklist this node for @config[:blacklist_duration] seconds
@@ -103,28 +102,21 @@ module Makara
103
102
 
104
103
  # we want to forward all private methods, since we could have kicked out from a private scenario
105
104
  def method_missing(m, *args, &block)
106
- if _makara_connection.respond_to?(m)
107
- _makara_connection.public_send(m, *args, &block)
108
- else # probably private method
109
- _makara_connection.__send__(m, *args, &block)
110
- end
105
+ _makara_connection.send(m, *args, &block)
111
106
  end
112
107
 
108
+ ruby2_keywords :method_missing if Module.private_method_defined?(:ruby2_keywords)
113
109
 
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
- _makara_connection.respond_to?(m, true)
117
- end
118
- RUBY_EVAL
119
-
110
+ def respond_to_missing?(m, include_private = false)
111
+ _makara_connection.respond_to?(m, true)
112
+ end
120
113
 
121
114
  protected
122
115
 
123
116
  # once the underlying connection is present we must evaluate extra functionality into it.
124
117
  # all extra functionality is in the format of _makara*
125
118
  def _makara_decorate_connection(con)
126
-
127
- extension = %Q{
119
+ extension = <<~RUBY
128
120
  # the proxy object controlling this connection
129
121
  def _makara
130
122
  @_makara
@@ -148,47 +140,52 @@ module Makara
148
140
  def _makara_name
149
141
  #{@config[:name].inspect}
150
142
  end
151
- }
143
+ RUBY
144
+
145
+ args = RUBY_VERSION >= "3.0.0" ? "..." : "*args, &block"
152
146
 
153
147
  # Each method the Makara::Proxy needs to hijack should be redefined in the underlying connection.
154
148
  # The new definition should allow for the proxy to intercept the invocation if required.
155
149
  @proxy.class.hijack_methods.each do |meth|
156
- extension << %Q{
157
- def #{meth}(*args, &block)
150
+ method_call = RUBY_VERSION >= "3.0.0" ? "public_send(#{meth.inspect}, ...)" : "#{meth}(*args, &block)"
151
+
152
+ extension << <<~RUBY
153
+ def #{meth}(#{args})
158
154
  _makara_hijack do |proxy|
159
155
  if proxy
160
- proxy.#{meth}(*args, &block)
156
+ proxy.#{method_call}
161
157
  else
162
158
  super
163
159
  end
164
160
  end
165
161
  end
166
- }
162
+ RUBY
167
163
  end
168
164
 
169
165
  # Control methods must always be passed to the
170
166
  # Makara::Proxy control object for handling (typically
171
167
  # related to ActiveRecord connection pool management)
172
168
  @proxy.class.control_methods.each do |meth|
173
- extension << %Q{
174
- def #{meth}(*args, &block)
169
+ method_call = RUBY_VERSION >= "3.0.0" ? "public_send(#{meth.inspect}, ...)" : "#{meth}(*args=args, block)"
170
+
171
+ extension << <<~RUBY
172
+ def #{meth}(#{args})
175
173
  proxy = _makara
176
174
  if proxy
177
- proxy.control.#{meth}(*args=args, block)
175
+ proxy.control.#{method_call}
178
176
  else
179
177
  super # Only if we are not wrapped any longer
180
178
  end
181
179
  end
182
- }
180
+ RUBY
183
181
  end
184
182
 
185
183
  # extend the instance
186
- con.instance_eval(extension)
184
+ con.instance_eval(extension, __FILE__, __LINE__ + 1)
187
185
  # set the makara context
188
186
  con._makara = @proxy
189
187
 
190
188
  con._makara
191
189
  end
192
-
193
190
  end
194
191
  end
@@ -123,6 +123,7 @@ module Makara
123
123
  end
124
124
 
125
125
  protected
126
+
126
127
  def current
127
128
  fetch(:makara_current_context) { new({}) }
128
129
  end
data/lib/makara/cookie.rb CHANGED
@@ -22,6 +22,7 @@ module Makara
22
22
  end
23
23
 
24
24
  private
25
+
25
26
  # Pairs of {proxy_id}:{timestamp}, separated by "|"
26
27
  # proxy_id1:1518270031.3132212|proxy_id2:1518270030.313232 ..
27
28
  def parse(cookie_string)
@@ -4,36 +4,27 @@
4
4
 
5
5
  module Makara
6
6
  class ErrorHandler
7
-
8
-
9
7
  def handle(connection)
10
8
  yield
11
-
12
9
  rescue Exception => e
13
-
14
10
  if e.is_a?(Makara::Errors::MakaraError)
15
11
  harshly(e)
16
12
  else
17
13
  gracefully(connection, e)
18
14
  end
19
-
20
15
  end
21
16
 
22
-
23
17
  protected
24
18
 
25
-
26
19
  def gracefully(connection, e)
27
20
  err = Makara::Errors::BlacklistConnection.new(connection, e)
28
21
  ::Makara::Logging::Logger.log("Gracefully handling: #{err}")
29
22
  raise err
30
23
  end
31
24
 
32
-
33
25
  def harshly(e)
34
26
  ::Makara::Logging::Logger.log("Harshly handling: #{e}\n#{e.backtrace.join("\n\t")}")
35
27
  raise e
36
28
  end
37
-
38
29
  end
39
30
  end
@@ -1,13 +1,11 @@
1
1
  module Makara
2
2
  module Errors
3
3
  class AllConnectionsBlacklisted < MakaraError
4
-
5
4
  def initialize(pool, errors)
6
5
  errors = [*errors]
7
6
  messages = errors.empty? ? 'No error details' : errors.map(&:message).join(' -> ')
8
7
  super "[Makara/#{pool.role}] All connections are blacklisted -> " + messages
9
8
  end
10
-
11
9
  end
12
10
  end
13
11
  end