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,14 +1,12 @@
|
|
1
1
|
module Makara
|
2
2
|
module Errors
|
3
3
|
class BlacklistConnection < MakaraError
|
4
|
-
|
5
4
|
attr_reader :original_error
|
6
5
|
|
7
6
|
def initialize(connection, error)
|
8
7
|
@original_error = error
|
9
8
|
super "[Makara/#{connection._makara_name}] #{error.message}"
|
10
9
|
end
|
11
|
-
|
12
10
|
end
|
13
11
|
end
|
14
12
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Makara
|
2
2
|
module Errors
|
3
3
|
class InvalidShard < MakaraError
|
4
|
-
|
5
4
|
attr_reader :role
|
6
5
|
attr_reader :shard_id
|
7
6
|
|
@@ -10,7 +9,6 @@ module Makara
|
|
10
9
|
@shard_id = shard_id
|
11
10
|
super "[Makara] Invalid shard_id #{shard_id} for the #{role} pool"
|
12
11
|
end
|
13
|
-
|
14
12
|
end
|
15
13
|
end
|
16
|
-
end
|
14
|
+
end
|
@@ -1,9 +1,7 @@
|
|
1
1
|
module Makara
|
2
2
|
module Logging
|
3
3
|
class Logger
|
4
|
-
|
5
4
|
class << self
|
6
|
-
|
7
5
|
def log(msg, format = :error)
|
8
6
|
logger.send(format, "[Makara] #{msg}") if logger
|
9
7
|
end
|
@@ -15,9 +13,7 @@ module Makara
|
|
15
13
|
def logger=(l)
|
16
14
|
@logger = l
|
17
15
|
end
|
18
|
-
|
19
16
|
end
|
20
|
-
|
21
17
|
end
|
22
18
|
end
|
23
19
|
end
|
data/lib/makara/middleware.rb
CHANGED
@@ -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
@@ -6,7 +6,6 @@ require 'makara/strategies/shard_aware'
|
|
6
6
|
|
7
7
|
module Makara
|
8
8
|
class Pool
|
9
|
-
|
10
9
|
# there are cases when we understand the pool is busted and we essentially want to skip
|
11
10
|
# all execution
|
12
11
|
attr_accessor :disabled
|
@@ -32,7 +31,6 @@ module Makara
|
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
|
-
|
36
34
|
def completely_blacklisted?
|
37
35
|
@connections.each do |connection|
|
38
36
|
return false unless connection._makara_blacklisted?
|
@@ -40,7 +38,6 @@ module Makara
|
|
40
38
|
true
|
41
39
|
end
|
42
40
|
|
43
|
-
|
44
41
|
# Add a connection to this pool, wrapping the connection with a Makara::ConnectionWrapper
|
45
42
|
def add(config)
|
46
43
|
config[:name] ||= "#{@role}/#{@connections.length + 1}"
|
@@ -70,6 +67,7 @@ module Makara
|
|
70
67
|
|
71
68
|
@connections.each do |con|
|
72
69
|
next if con._makara_blacklisted?
|
70
|
+
|
73
71
|
begin
|
74
72
|
ret = @proxy.error_handler.handle(con) do
|
75
73
|
if block
|
@@ -130,6 +128,7 @@ module Makara
|
|
130
128
|
in_transaction = self.role == "master" && provided_connection._makara_in_transaction?
|
131
129
|
provided_connection._makara_blacklist!
|
132
130
|
raise Makara::Errors::BlacklistedWhileInTransaction.new(@role) if in_transaction
|
131
|
+
|
133
132
|
attempt += 1
|
134
133
|
if attempt < @connections.length
|
135
134
|
retry
|
@@ -143,17 +142,13 @@ module Makara
|
|
143
142
|
end
|
144
143
|
end
|
145
144
|
|
146
|
-
|
147
|
-
|
148
145
|
protected
|
149
146
|
|
150
|
-
|
151
147
|
# have we connected to any of the underlying connections.
|
152
148
|
def connection_made?
|
153
149
|
@connections.any?(&:_makara_connected?)
|
154
150
|
end
|
155
151
|
|
156
|
-
|
157
152
|
# Get the next non-blacklisted connection. If the proxy is setup
|
158
153
|
# to be sticky, provide back the current connection assuming it is
|
159
154
|
# not blacklisted.
|
data/lib/makara/proxy.rb
CHANGED
@@ -11,7 +11,6 @@ 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
16
|
class_attribute :hijack_methods, :control_methods
|
@@ -24,19 +23,23 @@ module Makara
|
|
24
23
|
self.hijack_methods |= method_names
|
25
24
|
|
26
25
|
method_names.each do |method_name|
|
27
|
-
define_method
|
26
|
+
define_method(method_name) do |*args, &block|
|
28
27
|
appropriate_connection(method_name, args) do |con|
|
29
28
|
con.send(method_name, *args, &block)
|
30
29
|
end
|
31
30
|
end
|
31
|
+
|
32
|
+
ruby2_keywords method_name if Module.private_method_defined?(:ruby2_keywords)
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
35
36
|
def send_to_all(*method_names)
|
36
37
|
method_names.each do |method_name|
|
37
|
-
define_method
|
38
|
-
send_to_all
|
38
|
+
define_method(method_name) do |*args|
|
39
|
+
send_to_all(method_name, *args)
|
39
40
|
end
|
41
|
+
|
42
|
+
ruby2_keywords method_name if Module.private_method_defined?(:ruby2_keywords)
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
@@ -45,14 +48,15 @@ module Makara
|
|
45
48
|
self.control_methods |= method_names
|
46
49
|
|
47
50
|
method_names.each do |method_name|
|
48
|
-
define_method
|
51
|
+
define_method(method_name) do |*args, &block|
|
49
52
|
control&.send(method_name, *args, &block)
|
50
53
|
end
|
54
|
+
|
55
|
+
ruby2_keywords method_name if Module.private_method_defined?(:ruby2_keywords)
|
51
56
|
end
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
55
|
-
|
56
60
|
attr_reader :error_handler
|
57
61
|
attr_reader :sticky
|
58
62
|
attr_reader :config_parser
|
@@ -118,27 +122,25 @@ module Makara
|
|
118
122
|
|
119
123
|
def method_missing(m, *args, &block)
|
120
124
|
if METHOD_MISSING_SKIP.include?(m)
|
121
|
-
return super
|
125
|
+
return super
|
122
126
|
end
|
123
127
|
|
124
128
|
any_connection do |con|
|
125
|
-
if con.respond_to?(m)
|
126
|
-
con.
|
127
|
-
elsif con.respond_to?(m, true)
|
128
|
-
con.__send__(m, *args, &block)
|
129
|
+
if con.respond_to?(m, true)
|
130
|
+
con.send(m, *args, &block)
|
129
131
|
else
|
130
|
-
super
|
132
|
+
super
|
131
133
|
end
|
132
134
|
end
|
133
135
|
end
|
134
136
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
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)
|
140
142
|
end
|
141
|
-
|
143
|
+
end
|
142
144
|
|
143
145
|
def graceful_connection_for(config)
|
144
146
|
fake_wrapper = Makara::ConnectionWrapper.new(self, nil, config)
|
@@ -159,15 +161,16 @@ module Makara
|
|
159
161
|
|
160
162
|
protected
|
161
163
|
|
162
|
-
|
163
164
|
def send_to_all(method_name, *args)
|
164
165
|
# slave pool must run first to allow for slave-->master failover without running operations on master twice.
|
165
166
|
handling_an_all_execution(method_name) do
|
166
|
-
@slave_pool.send_to_all
|
167
|
-
@master_pool.send_to_all
|
167
|
+
@slave_pool.send_to_all(method_name, *args)
|
168
|
+
@master_pool.send_to_all(method_name, *args)
|
168
169
|
end
|
169
170
|
end
|
170
171
|
|
172
|
+
ruby2_keywords :send_to_all if Module.private_method_defined?(:ruby2_keywords)
|
173
|
+
|
171
174
|
def any_connection
|
172
175
|
if @master_pool.disabled
|
173
176
|
@slave_pool.provide do |con|
|
@@ -202,14 +205,11 @@ module Makara
|
|
202
205
|
end
|
203
206
|
end
|
204
207
|
|
205
|
-
|
206
208
|
# master or slave
|
207
209
|
def appropriate_pool(method_name, args)
|
208
|
-
|
209
210
|
# for testing purposes
|
210
211
|
pool = _appropriate_pool(method_name, args)
|
211
212
|
yield pool
|
212
|
-
|
213
213
|
rescue ::Makara::Errors::AllConnectionsBlacklisted, ::Makara::Errors::NoConnectionsAvailable => e
|
214
214
|
if pool == @master_pool
|
215
215
|
@master_pool.connections.each(&:_makara_whitelist!)
|
@@ -268,7 +268,6 @@ module Makara
|
|
268
268
|
@hijacked = false
|
269
269
|
end
|
270
270
|
|
271
|
-
|
272
271
|
def stuck_to_master?
|
273
272
|
sticky? && Makara::Context.stuck?(@id)
|
274
273
|
end
|
@@ -316,16 +315,15 @@ module Makara
|
|
316
315
|
# this means slave connections are good.
|
317
316
|
return
|
318
317
|
end
|
318
|
+
|
319
319
|
@slave_pool.disabled = true
|
320
320
|
yield
|
321
321
|
ensure
|
322
322
|
@slave_pool.disabled = false
|
323
323
|
end
|
324
324
|
|
325
|
-
|
326
325
|
def connection_for(config)
|
327
326
|
Kernel.raise NotImplementedError
|
328
327
|
end
|
329
|
-
|
330
328
|
end
|
331
329
|
end
|
data/lib/makara/railtie.rb
CHANGED
@@ -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
|
@@ -3,7 +3,6 @@ require 'makara/errors/invalid_shard'
|
|
3
3
|
module Makara
|
4
4
|
module Strategies
|
5
5
|
class ShardAware < ::Makara::Strategies::Abstract
|
6
|
-
|
7
6
|
def init
|
8
7
|
@shards = {}
|
9
8
|
@default_shard = pool.default_shard
|
@@ -41,7 +40,6 @@ module Makara
|
|
41
40
|
def shard_id
|
42
41
|
Thread.current['makara_shard_id'] || pool.default_shard
|
43
42
|
end
|
44
|
-
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
data/lib/makara/version.rb
CHANGED
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,11 +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 = "https://github.com/
|
8
|
+
gem.homepage = "https://github.com/instacart/makara"
|
10
9
|
gem.licenses = ['MIT']
|
11
10
|
gem.metadata = {
|
12
|
-
|
13
|
-
|
11
|
+
"source_code_uri" => 'https://github.com/instacart/makara'
|
12
|
+
}
|
14
13
|
|
15
14
|
gem.files = `git ls-files`.split($\)
|
16
15
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -19,5 +18,25 @@ Gem::Specification.new do |gem|
|
|
19
18
|
gem.require_paths = ["lib"]
|
20
19
|
gem.version = Makara::VERSION
|
21
20
|
|
22
|
-
gem.
|
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
|
23
42
|
end
|