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.
- 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
|