makara 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +11 -0
- data/.github/workflows/CI.yml +88 -0
- data/.rspec +1 -1
- data/.rubocop.yml +15 -0
- data/.rubocop_todo.yml +670 -0
- data/CHANGELOG.md +14 -6
- data/Gemfile +1 -16
- data/README.md +2 -1
- data/Rakefile +1 -1
- data/gemfiles/activerecord_5.2.gemfile +8 -0
- data/gemfiles/activerecord_6.0.gemfile +8 -0
- data/gemfiles/activerecord_6.1.gemfile +8 -0
- data/gemfiles/activerecord_head.gemfile +6 -0
- data/lib/active_record/connection_adapters/jdbcmysql_makara_adapter.rb +4 -18
- data/lib/active_record/connection_adapters/jdbcpostgresql_makara_adapter.rb +4 -18
- data/lib/active_record/connection_adapters/makara_abstract_adapter.rb +3 -31
- data/lib/active_record/connection_adapters/makara_jdbcmysql_adapter.rb +4 -18
- data/lib/active_record/connection_adapters/makara_jdbcpostgresql_adapter.rb +4 -18
- data/lib/active_record/connection_adapters/makara_mysql2_adapter.rb +4 -20
- data/lib/active_record/connection_adapters/makara_postgis_adapter.rb +4 -19
- data/lib/active_record/connection_adapters/makara_postgresql_adapter.rb +4 -20
- data/lib/active_record/connection_adapters/mysql2_makara_adapter.rb +4 -20
- data/lib/active_record/connection_adapters/postgresql_makara_adapter.rb +4 -20
- data/lib/makara.rb +0 -2
- data/lib/makara/cache.rb +0 -2
- data/lib/makara/config_parser.rb +5 -14
- data/lib/makara/connection_wrapper.rb +24 -27
- data/lib/makara/context.rb +1 -0
- data/lib/makara/cookie.rb +1 -0
- data/lib/makara/error_handler.rb +0 -9
- data/lib/makara/errors/all_connections_blacklisted.rb +0 -2
- data/lib/makara/errors/blacklist_connection.rb +0 -2
- data/lib/makara/errors/blacklisted_while_in_transaction.rb +0 -2
- data/lib/makara/errors/invalid_shard.rb +1 -3
- data/lib/makara/errors/makara_error.rb +0 -1
- data/lib/makara/errors/no_connections_available.rb +0 -2
- data/lib/makara/logging/logger.rb +0 -4
- data/lib/makara/logging/subscriber.rb +0 -2
- data/lib/makara/middleware.rb +1 -2
- data/lib/makara/pool.rb +2 -7
- data/lib/makara/proxy.rb +25 -27
- data/lib/makara/railtie.rb +0 -2
- data/lib/makara/strategies/abstract.rb +1 -0
- data/lib/makara/strategies/priority_failover.rb +2 -0
- data/lib/makara/strategies/round_robin.rb +1 -3
- data/lib/makara/strategies/shard_aware.rb +0 -2
- data/lib/makara/version.rb +1 -3
- data/makara.gemspec +24 -5
- data/spec/active_record/connection_adapters/makara_abstract_adapter_error_handling_spec.rb +1 -6
- data/spec/active_record/connection_adapters/makara_abstract_adapter_spec.rb +0 -9
- data/spec/active_record/connection_adapters/makara_mysql2_adapter_spec.rb +9 -22
- data/spec/active_record/connection_adapters/makara_postgis_adapter_spec.rb +2 -10
- data/spec/active_record/connection_adapters/makara_postgresql_adapter_spec.rb +7 -20
- data/spec/cache_spec.rb +0 -1
- data/spec/config_parser_spec.rb +54 -56
- data/spec/connection_wrapper_spec.rb +1 -2
- data/spec/cookie_spec.rb +1 -1
- data/spec/middleware_spec.rb +1 -1
- data/spec/pool_spec.rb +3 -16
- data/spec/proxy_spec.rb +0 -4
- data/spec/spec_helper.rb +5 -1
- data/spec/strategies/priority_failover_spec.rb +3 -4
- data/spec/strategies/round_robin_spec.rb +4 -8
- data/spec/strategies/shard_aware_spec.rb +4 -5
- data/spec/support/deep_dup.rb +1 -1
- data/spec/support/helpers.rb +5 -5
- data/spec/support/mock_objects.rb +1 -4
- data/spec/support/mysql2_database.yml +2 -2
- data/spec/support/mysql2_database_with_custom_errors.yml +2 -2
- data/spec/support/pool_extensions.rb +0 -3
- data/spec/support/postgis_schema.rb +1 -1
- data/spec/support/postgresql_database.yml +0 -2
- data/spec/support/proxy_extensions.rb +1 -3
- data/spec/support/schema.rb +1 -1
- data/spec/support/user.rb +1 -2
- metadata +156 -20
- data/.travis.yml +0 -131
- data/gemfiles/ar-head.gemfile +0 -24
- data/gemfiles/ar30.gemfile +0 -36
- data/gemfiles/ar31.gemfile +0 -36
- data/gemfiles/ar32.gemfile +0 -36
- data/gemfiles/ar40.gemfile +0 -24
- data/gemfiles/ar41.gemfile +0 -24
- data/gemfiles/ar42.gemfile +0 -24
- data/gemfiles/ar50.gemfile +0 -24
- data/gemfiles/ar51.gemfile +0 -24
- data/gemfiles/ar52.gemfile +0 -24
- 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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
data/lib/makara/config_parser.rb
CHANGED
@@ -20,11 +20,10 @@ require 'cgi'
|
|
20
20
|
|
21
21
|
module Makara
|
22
22
|
class ConfigParser
|
23
|
-
|
24
23
|
DEFAULTS = {
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
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
|
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
|
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
|
-
|
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
|
-
|
115
|
-
|
116
|
-
|
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
|
-
|
157
|
-
|
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.#{
|
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
|
-
|
174
|
-
|
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.#{
|
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
|
data/lib/makara/context.rb
CHANGED
data/lib/makara/cookie.rb
CHANGED
data/lib/makara/error_handler.rb
CHANGED
@@ -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
|