makara 0.3.7 → 0.3.8
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/.travis.yml +55 -14
- data/CHANGELOG.md +2 -2
- data/gemfiles/ar-head.gemfile +15 -0
- data/gemfiles/ar50.gemfile +15 -0
- data/gemfiles/ar51.gemfile +15 -0
- data/lib/active_record/connection_adapters/makara_abstract_adapter.rb +12 -3
- data/lib/makara.rb +1 -0
- data/lib/makara/connection_wrapper.rb +1 -1
- data/lib/makara/context.rb +48 -11
- data/lib/makara/error_handler.rb +1 -1
- data/lib/makara/errors/all_connections_blacklisted.rb +1 -1
- data/lib/makara/errors/blacklist_connection.rb +1 -1
- data/lib/makara/errors/makara_error.rb +7 -0
- data/lib/makara/errors/no_connections_available.rb +1 -1
- data/lib/makara/middleware.rb +11 -12
- data/lib/makara/proxy.rb +14 -8
- data/lib/makara/version.rb +1 -1
- data/spec/active_record/connection_adapters/makara_mysql2_adapter_spec.rb +49 -43
- data/spec/active_record/connection_adapters/makara_postgresql_adapter_spec.rb +6 -7
- data/spec/connection_wrapper_spec.rb +14 -7
- data/spec/context_spec.rb +39 -0
- data/spec/middleware_spec.rb +2 -2
- data/spec/spec_helper.rb +2 -2
- data/spec/support/helpers.rb +23 -0
- data/spec/support/schema.rb +3 -1
- metadata +9 -7
- data/.ruby-version +0 -1
- data/spec/support/configurator.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a43f7871351a95b0291a4624bdfded3e1e4bccf3
|
4
|
+
data.tar.gz: feaf04905d1a7293abd47cf32a0f69f23575c609
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06ce4185196b043f4129039a18a55db3f18816ab8af517372193ac28e2cf8517b4dd0abee9970ab012b0a0f2214fd56e42fcd3fce5643d077a8aa3537bbd4635
|
7
|
+
data.tar.gz: a45e25f35d71242f954d4a5fdeafeb0907399b496d19c9122e227ad04bd0486986ce37e2390877f191a2adc0e7295a37ecade58278c57991b57f6152da3123b1
|
data/.travis.yml
CHANGED
@@ -1,8 +1,22 @@
|
|
1
|
+
sudo: false
|
1
2
|
language: ruby
|
3
|
+
cache: bundler
|
4
|
+
|
5
|
+
services:
|
6
|
+
- mysql
|
7
|
+
- postgresql
|
8
|
+
|
9
|
+
before_script:
|
10
|
+
- mysql -e 'create database makara_test;'
|
11
|
+
- psql -c 'create database makara_test;' -U postgres
|
2
12
|
|
3
13
|
rvm:
|
4
|
-
- 2.0
|
5
|
-
- 2.1
|
14
|
+
- 2.0
|
15
|
+
- 2.1
|
16
|
+
- 2.2
|
17
|
+
- 2.3
|
18
|
+
- 2.4
|
19
|
+
- ruby-head
|
6
20
|
- jruby
|
7
21
|
|
8
22
|
gemfile:
|
@@ -12,17 +26,44 @@ gemfile:
|
|
12
26
|
- gemfiles/ar40.gemfile
|
13
27
|
- gemfiles/ar41.gemfile
|
14
28
|
- gemfiles/ar42.gemfile
|
29
|
+
- gemfiles/ar50.gemfile
|
30
|
+
- gemfiles/ar51.gemfile
|
31
|
+
- gemfiles/ar-head.gemfile
|
15
32
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
- mysql
|
20
|
-
- postgresql
|
21
|
-
|
22
|
-
before_script:
|
23
|
-
- mysql -e 'create database makara_test;'
|
24
|
-
- psql -c 'create database makara_test;' -U postgres
|
33
|
+
env:
|
34
|
+
global:
|
35
|
+
- "JRUBY_OPTS='--dev -J-Xmx1024M'"
|
25
36
|
|
26
|
-
|
27
|
-
|
28
|
-
|
37
|
+
matrix:
|
38
|
+
exclude:
|
39
|
+
- gemfile: gemfiles/ar30.gemfile
|
40
|
+
rvm: 2.2
|
41
|
+
- gemfile: gemfiles/ar30.gemfile
|
42
|
+
rvm: 2.3
|
43
|
+
- gemfile: gemfiles/ar30.gemfile
|
44
|
+
rvm: 2.4
|
45
|
+
- gemfile: gemfiles/ar30.gemfile
|
46
|
+
rvm: ruby-head
|
47
|
+
- gemfile: gemfiles/ar50.gemfile
|
48
|
+
rvm: 2.0
|
49
|
+
- gemfile: gemfiles/ar50.gemfile
|
50
|
+
rvm: 2.1
|
51
|
+
- gemfile: gemfiles/ar50.gemfile
|
52
|
+
rvm: 2.2
|
53
|
+
- gemfile: gemfiles/ar51.gemfile
|
54
|
+
rvm: 2.0
|
55
|
+
- gemfile: gemfiles/ar51.gemfile
|
56
|
+
rvm: 2.1
|
57
|
+
- gemfile: gemfiles/ar51.gemfile
|
58
|
+
rvm: 2.2
|
59
|
+
- gemfile: gemfiles/ar-head.gemfile
|
60
|
+
rvm: 2.0
|
61
|
+
- gemfile: gemfiles/ar-head.gemfile
|
62
|
+
rvm: 2.1
|
63
|
+
- gemfile: gemfiles/ar-head.gemfile
|
64
|
+
rvm: 2.2
|
65
|
+
allow_failures:
|
66
|
+
- gemfile: gemfiles/ar-head.gemfile
|
67
|
+
- rvm: ruby-head
|
68
|
+
- rvm: jruby
|
69
|
+
fast_finish: true
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
-
## v0.3.7
|
4
|
+
## v0.3.7 - 2016-09-22
|
5
5
|
|
6
|
-
[Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.6...v0.3.7
|
6
|
+
[Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.6...v0.3.7)
|
7
7
|
|
8
8
|
Changed
|
9
9
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in makara.gemspec
|
4
|
+
gemspec :path => '../'
|
5
|
+
|
6
|
+
|
7
|
+
gem 'rake'
|
8
|
+
gem 'activerecord', :git => 'https://github.com/rails/rails'
|
9
|
+
gem 'rspec'
|
10
|
+
gem 'rack'
|
11
|
+
gem 'timecop'
|
12
|
+
gem 'mysql2', :platform => :ruby
|
13
|
+
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
|
+
gem 'pg', :platform => :ruby
|
15
|
+
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in makara.gemspec
|
4
|
+
gemspec :path => '../'
|
5
|
+
|
6
|
+
|
7
|
+
gem 'rake'
|
8
|
+
gem 'activerecord', '~> 5.0.0'
|
9
|
+
gem 'rspec'
|
10
|
+
gem 'rack'
|
11
|
+
gem 'timecop'
|
12
|
+
gem 'mysql2', :platform => :ruby
|
13
|
+
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
|
+
gem 'pg', :platform => :ruby
|
15
|
+
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in makara.gemspec
|
4
|
+
gemspec :path => '../'
|
5
|
+
|
6
|
+
|
7
|
+
gem 'rake'
|
8
|
+
gem 'activerecord', '~> 5.1.0'
|
9
|
+
gem 'rspec'
|
10
|
+
gem 'rack'
|
11
|
+
gem 'timecop'
|
12
|
+
gem 'mysql2', :platform => :ruby
|
13
|
+
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
|
+
gem 'pg', :platform => :ruby
|
15
|
+
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
@@ -165,27 +165,36 @@ module ActiveRecord
|
|
165
165
|
|
166
166
|
|
167
167
|
def should_stick?(method_name, args)
|
168
|
-
sql = args.first
|
168
|
+
sql = coerce_query_to_sql_string(args.first)
|
169
169
|
return false if sql_skip_stickiness_matchers.any?{|m| sql =~ m }
|
170
170
|
super
|
171
171
|
end
|
172
172
|
|
173
173
|
|
174
174
|
def needed_by_all?(method_name, args)
|
175
|
-
sql = args.first
|
175
|
+
sql = coerce_query_to_sql_string(args.first)
|
176
176
|
return true if sql_all_matchers.any?{|m| sql =~ m }
|
177
177
|
false
|
178
178
|
end
|
179
179
|
|
180
180
|
|
181
181
|
def needs_master?(method_name, args)
|
182
|
-
sql = args.first
|
182
|
+
sql = coerce_query_to_sql_string(args.first)
|
183
183
|
return true if sql_master_matchers.any?{|m| sql =~ m }
|
184
184
|
return false if sql_slave_matchers.any?{|m| sql =~ m }
|
185
185
|
true
|
186
186
|
end
|
187
187
|
|
188
188
|
|
189
|
+
def coerce_query_to_sql_string(sql_or_arel)
|
190
|
+
if sql_or_arel.respond_to?(:to_sql)
|
191
|
+
sql_or_arel.to_sql
|
192
|
+
else
|
193
|
+
sql_or_arel.to_s
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
|
189
198
|
def connection_for(config)
|
190
199
|
config = Makara::ConfigParser.merge_and_resolve_default_url_config(config)
|
191
200
|
active_record_connection_for(config)
|
data/lib/makara.rb
CHANGED
@@ -12,6 +12,7 @@ module Makara
|
|
12
12
|
autoload :Proxy, 'makara/proxy'
|
13
13
|
|
14
14
|
module Errors
|
15
|
+
autoload :MakaraError, 'makara/errors/makara_error'
|
15
16
|
autoload :AllConnectionsBlacklisted, 'makara/errors/all_connections_blacklisted'
|
16
17
|
autoload :BlacklistConnection, 'makara/errors/blacklist_connection'
|
17
18
|
autoload :NoConnectionsAvailable, 'makara/errors/no_connections_available'
|
@@ -37,7 +37,7 @@ module Makara
|
|
37
37
|
|
38
38
|
# has this node been blacklisted?
|
39
39
|
def _makara_blacklisted?
|
40
|
-
@blacklisted_until.to_i > Time.now.to_i
|
40
|
+
@blacklisted_until.present? && @blacklisted_until.to_i > Time.now.to_i
|
41
41
|
end
|
42
42
|
|
43
43
|
# blacklist this node for @config[:blacklist_duration] seconds
|
data/lib/makara/context.rb
CHANGED
@@ -13,32 +13,69 @@ module Makara
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def get_previous
|
16
|
-
|
16
|
+
fetch(:makara_context_previous) { generate }
|
17
17
|
end
|
18
18
|
|
19
19
|
def set_previous(context)
|
20
|
-
|
20
|
+
previously_sticky.clear
|
21
|
+
set(:makara_context_previous,context)
|
21
22
|
end
|
22
23
|
|
23
24
|
def get_current
|
24
|
-
|
25
|
+
fetch(:makara_context_current) { generate }
|
25
26
|
end
|
26
27
|
|
27
28
|
def set_current(context)
|
28
|
-
|
29
|
+
set(:makara_context_current,context)
|
30
|
+
end
|
31
|
+
|
32
|
+
def previously_stuck?(config_id)
|
33
|
+
previously_sticky.fetch(config_id) do
|
34
|
+
stuck?(Makara::Context.get_previous, config_id)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Called by `Proxy#stick_to_master!` to stick subsequent requests to
|
39
|
+
# master. They'll see the current context as their previous context
|
40
|
+
# when they're asking whether they should be stuck to master.
|
41
|
+
def stick(context, config_id, ttl)
|
42
|
+
Makara::Cache.write(cache_key_for(context, config_id), '1', ttl)
|
43
|
+
end
|
44
|
+
|
45
|
+
def stuck?(context, config_id)
|
46
|
+
!!Makara::Cache.read(cache_key_for(context, config_id))
|
29
47
|
end
|
30
48
|
|
31
49
|
protected
|
32
50
|
|
33
|
-
def
|
34
|
-
|
35
|
-
current = t.respond_to?(:thread_variable_get) ? t.thread_variable_get(type) : t[type]
|
36
|
-
current ||= set_current_thread_local(type,generate)
|
51
|
+
def previously_sticky
|
52
|
+
fetch(:makara_previously_sticky) { Hash.new }
|
37
53
|
end
|
38
54
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
55
|
+
def cache_key_for(context, config_id)
|
56
|
+
"makara::#{context}-#{config_id}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def fetch(key)
|
60
|
+
get(key) || set(key,yield)
|
61
|
+
end
|
62
|
+
|
63
|
+
if Thread.current.respond_to?(:thread_variable_get)
|
64
|
+
def get(key)
|
65
|
+
Thread.current.thread_variable_get(key)
|
66
|
+
end
|
67
|
+
|
68
|
+
def set(key,value)
|
69
|
+
Thread.current.thread_variable_set(key,value)
|
70
|
+
end
|
71
|
+
else
|
72
|
+
def get(key)
|
73
|
+
Thread.current[key]
|
74
|
+
end
|
75
|
+
|
76
|
+
def set(key,value)
|
77
|
+
Thread.current[key]=value
|
78
|
+
end
|
42
79
|
end
|
43
80
|
|
44
81
|
end
|
data/lib/makara/error_handler.rb
CHANGED
data/lib/makara/middleware.rb
CHANGED
@@ -10,9 +10,15 @@ module Makara
|
|
10
10
|
|
11
11
|
IDENTIFIER = '_mkra_ctxt'
|
12
12
|
|
13
|
+
DEFAULT_COOKIE = {
|
14
|
+
:path => '/',
|
15
|
+
:http_only => true,
|
16
|
+
:max_age => '5'
|
17
|
+
}
|
13
18
|
|
14
|
-
def initialize(app)
|
19
|
+
def initialize(app, cookie_options = {})
|
15
20
|
@app = app
|
21
|
+
@cookie = DEFAULT_COOKIE.merge(cookie_options)
|
16
22
|
end
|
17
23
|
|
18
24
|
|
@@ -37,7 +43,7 @@ module Makara
|
|
37
43
|
# ignore asset paths
|
38
44
|
# consider allowing a filter proc to be provided in an initializer
|
39
45
|
def ignore_request?(env)
|
40
|
-
if defined?(Rails)
|
46
|
+
if defined?(Rails) && Rails.try(:application).try(:config).try(:assets).try(:prefix)
|
41
47
|
if env['PATH_INFO'].to_s =~ /^#{Rails.application.config.assets.prefix}/
|
42
48
|
return true
|
43
49
|
end
|
@@ -94,16 +100,9 @@ module Makara
|
|
94
100
|
# it should always be for the same path, only
|
95
101
|
# accessible via http and live for a short amount
|
96
102
|
# of time
|
97
|
-
def store_context(status,
|
98
|
-
|
99
|
-
|
100
|
-
:path => '/',
|
101
|
-
:value => "#{Makara::Context.get_current}--#{status}",
|
102
|
-
:http_only => true,
|
103
|
-
:max_age => '5'
|
104
|
-
}
|
105
|
-
|
106
|
-
Rack::Utils.set_cookie_header!(header, IDENTIFIER, cookie_value)
|
103
|
+
def store_context(status, headers)
|
104
|
+
cookie = @cookie.merge(:value => "#{Makara::Context.get_current}--#{status}")
|
105
|
+
Rack::Utils.set_cookie_header! headers, IDENTIFIER, cookie
|
107
106
|
end
|
108
107
|
end
|
109
108
|
end
|
data/lib/makara/proxy.rb
CHANGED
@@ -74,18 +74,26 @@ module Makara
|
|
74
74
|
|
75
75
|
def stick_to_master!(write_to_cache = true)
|
76
76
|
@master_context = Makara::Context.get_current
|
77
|
-
Makara::
|
77
|
+
Makara::Context.stick(@master_context, @id, @ttl) if write_to_cache
|
78
78
|
end
|
79
79
|
|
80
80
|
def strategy_for(role)
|
81
|
-
|
81
|
+
strategy_class_for(strategy_name_for(role)).new(self)
|
82
|
+
end
|
83
|
+
|
84
|
+
def strategy_name_for(role)
|
85
|
+
@config_parser.makara_config["#{role}_strategy".to_sym]
|
86
|
+
end
|
87
|
+
|
88
|
+
def strategy_class_for(strategy_name)
|
82
89
|
case strategy_name
|
83
90
|
when 'round_robin', 'roundrobin', nil, ''
|
84
|
-
|
91
|
+
::Makara::Strategies::RoundRobin
|
85
92
|
when 'failover'
|
86
|
-
|
93
|
+
::Makara::Strategies::PriorityFailover
|
94
|
+
else
|
95
|
+
strategy_name.constantize
|
87
96
|
end
|
88
|
-
strategy_name.constantize.new(self)
|
89
97
|
end
|
90
98
|
|
91
99
|
def method_missing(m, *args, &block)
|
@@ -198,7 +206,6 @@ module Makara
|
|
198
206
|
elsif Makara::Context.get_current == @master_context
|
199
207
|
@master_pool
|
200
208
|
|
201
|
-
# the previous context stuck us to master
|
202
209
|
elsif previously_stuck_to_master?
|
203
210
|
|
204
211
|
# we're only on master because of the previous context so
|
@@ -242,8 +249,7 @@ module Makara
|
|
242
249
|
|
243
250
|
|
244
251
|
def previously_stuck_to_master?
|
245
|
-
|
246
|
-
!!Makara::Cache.read("makara::#{Makara::Context.get_previous}-#{@id}")
|
252
|
+
@sticky && Makara::Context.previously_stuck?(@id)
|
247
253
|
end
|
248
254
|
|
249
255
|
|
data/lib/makara/version.rb
CHANGED
@@ -20,50 +20,12 @@ describe 'MakaraMysql2Adapter' do
|
|
20
20
|
context "unconnected" do
|
21
21
|
|
22
22
|
it 'should allow a connection to be established' do
|
23
|
-
|
23
|
+
establish_connection(config)
|
24
24
|
expect(ActiveRecord::Base.connection).to be_instance_of(ActiveRecord::ConnectionAdapters::MakaraMysql2Adapter)
|
25
25
|
end
|
26
26
|
|
27
|
-
it 'should not blow up if a connection fails' do
|
28
|
-
wrong_config = config.deep_dup
|
29
|
-
wrong_config['makara']['connections'].select{|h| h['role'] == 'slave' }.each{|h| h['username'] = 'other'}
|
30
|
-
|
31
|
-
original_method = ActiveRecord::Base.method(:mysql2_connection)
|
32
|
-
|
33
|
-
allow(ActiveRecord::Base).to receive(:mysql2_connection) do |config|
|
34
|
-
if config[:username] == 'other'
|
35
|
-
raise "could not connect"
|
36
|
-
else
|
37
|
-
original_method.call(config)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
ActiveRecord::Base.establish_connection(wrong_config)
|
42
|
-
ActiveRecord::Base.connection
|
43
|
-
|
44
|
-
load(File.dirname(__FILE__) + '/../../support/schema.rb')
|
45
|
-
Makara::Context.set_current Makara::Context.generate
|
46
|
-
|
47
|
-
allow(ActiveRecord::Base).to receive(:mysql2_connection) do |config|
|
48
|
-
config[:username] = db_username
|
49
|
-
original_method.call(config)
|
50
|
-
end
|
51
|
-
|
52
|
-
ActiveRecord::Base.connection.slave_pool.connections.each(&:_makara_whitelist!)
|
53
|
-
ActiveRecord::Base.connection.slave_pool.provide do |con|
|
54
|
-
res = con.execute('SELECT count(*) FROM users')
|
55
|
-
if defined?(JRUBY_VERSION)
|
56
|
-
expect(res[0]).to eq('count(*)' => 0)
|
57
|
-
else
|
58
|
-
expect(res.to_a[0][0]).to eq(0)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
ActiveRecord::Base.remove_connection
|
63
|
-
end
|
64
|
-
|
65
27
|
it 'should execute a send_to_all against master even if no slaves are connected' do
|
66
|
-
|
28
|
+
establish_connection(config)
|
67
29
|
connection = ActiveRecord::Base.connection
|
68
30
|
|
69
31
|
connection.slave_pool.connections.each do |c|
|
@@ -82,7 +44,7 @@ describe 'MakaraMysql2Adapter' do
|
|
82
44
|
end
|
83
45
|
|
84
46
|
it 'should execute a send_to_all and raise a NoConnectionsAvailable error' do
|
85
|
-
|
47
|
+
establish_connection(config)
|
86
48
|
connection = ActiveRecord::Base.connection
|
87
49
|
|
88
50
|
(connection.slave_pool.connections | connection.master_pool.connections).each do |c|
|
@@ -97,12 +59,56 @@ describe 'MakaraMysql2Adapter' do
|
|
97
59
|
|
98
60
|
end
|
99
61
|
|
62
|
+
context "unconnect afterwards" do
|
63
|
+
after :each do
|
64
|
+
ActiveRecord::Base.clear_all_connections!
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should not blow up if a connection fails' do
|
68
|
+
wrong_config = config.deep_dup
|
69
|
+
wrong_config['makara']['connections'].select{|h| h['role'] == 'slave' }.each{|h| h['username'] = 'other'}
|
70
|
+
|
71
|
+
original_method = ActiveRecord::Base.method(:mysql2_connection)
|
72
|
+
|
73
|
+
allow(ActiveRecord::Base).to receive(:mysql2_connection) do |config|
|
74
|
+
if config[:username] == 'other'
|
75
|
+
raise "could not connect"
|
76
|
+
else
|
77
|
+
original_method.call(config)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
establish_connection(wrong_config)
|
82
|
+
ActiveRecord::Base.connection
|
83
|
+
|
84
|
+
load(File.dirname(__FILE__) + '/../../support/schema.rb')
|
85
|
+
Makara::Context.set_current Makara::Context.generate
|
86
|
+
|
87
|
+
allow(ActiveRecord::Base).to receive(:mysql2_connection) do |config|
|
88
|
+
config[:username] = db_username
|
89
|
+
original_method.call(config)
|
90
|
+
end
|
91
|
+
|
92
|
+
ActiveRecord::Base.connection.slave_pool.connections.each(&:_makara_whitelist!)
|
93
|
+
ActiveRecord::Base.connection.slave_pool.provide do |con|
|
94
|
+
res = con.execute('SELECT count(*) FROM users')
|
95
|
+
if defined?(JRUBY_VERSION)
|
96
|
+
expect(res[0]).to eq('count(*)' => 0)
|
97
|
+
else
|
98
|
+
expect(res.to_a[0][0]).to eq(0)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
ActiveRecord::Base.remove_connection
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
100
106
|
end
|
101
107
|
|
102
108
|
context 'with the connection established and schema loaded' do
|
103
109
|
|
104
110
|
before do
|
105
|
-
|
111
|
+
establish_connection(config)
|
106
112
|
load(File.dirname(__FILE__) + '/../../support/schema.rb')
|
107
113
|
change_context
|
108
114
|
end
|
@@ -183,7 +189,7 @@ describe 'MakaraMysql2Adapter' do
|
|
183
189
|
describe 'transaction support' do
|
184
190
|
shared_examples 'a transaction supporter' do
|
185
191
|
before do
|
186
|
-
|
192
|
+
establish_connection(config)
|
187
193
|
load(File.dirname(__FILE__) + '/../../support/schema.rb')
|
188
194
|
change_context
|
189
195
|
|
@@ -20,15 +20,14 @@ describe 'MakaraPostgreSQLAdapter' do
|
|
20
20
|
|
21
21
|
|
22
22
|
it 'should allow a connection to be established' do
|
23
|
-
|
23
|
+
establish_connection(config)
|
24
24
|
expect(ActiveRecord::Base.connection).to be_instance_of(ActiveRecord::ConnectionAdapters::MakaraPostgreSQLAdapter)
|
25
25
|
end
|
26
26
|
|
27
27
|
context 'with the connection established and schema loaded' do
|
28
28
|
|
29
29
|
before do
|
30
|
-
|
31
|
-
ActiveRecord::Base.establish_connection(config)
|
30
|
+
establish_connection(config)
|
32
31
|
load(File.dirname(__FILE__) + '/../../support/schema.rb')
|
33
32
|
change_context
|
34
33
|
end
|
@@ -95,7 +94,7 @@ describe 'MakaraPostgreSQLAdapter' do
|
|
95
94
|
custom_config = config.deep_dup
|
96
95
|
custom_config['makara']['connections'].select{|h| h['role'] == 'slave' }.each{|h| h['port'] = '1'}
|
97
96
|
|
98
|
-
|
97
|
+
establish_connection(custom_config)
|
99
98
|
load(File.dirname(__FILE__) + '/../../support/schema.rb')
|
100
99
|
|
101
100
|
connection.execute('SELECT * FROM users')
|
@@ -105,14 +104,14 @@ describe 'MakaraPostgreSQLAdapter' do
|
|
105
104
|
|
106
105
|
context 'with only slave connection' do
|
107
106
|
it 'should raise error only on write' do
|
108
|
-
|
107
|
+
establish_connection(config)
|
109
108
|
load(File.dirname(__FILE__) + '/../../support/schema.rb')
|
110
109
|
ActiveRecord::Base.clear_all_connections!
|
111
110
|
|
112
111
|
custom_config = config.deep_dup
|
113
112
|
custom_config['makara']['connections'].select{|h| h['role'] == 'master' }.each{|h| h['port'] = '1'}
|
114
113
|
|
115
|
-
|
114
|
+
establish_connection(custom_config)
|
116
115
|
|
117
116
|
connection.execute('SELECT * FROM users')
|
118
117
|
expect { connection.execute('INSERT INTO users (name) VALUES (\'John\')') }.to raise_error(Makara::Errors::NoConnectionsAvailable)
|
@@ -122,7 +121,7 @@ describe 'MakaraPostgreSQLAdapter' do
|
|
122
121
|
describe 'transaction support' do
|
123
122
|
shared_examples 'a transaction supporter' do
|
124
123
|
before do
|
125
|
-
|
124
|
+
establish_connection(config)
|
126
125
|
load(File.dirname(__FILE__) + '/../../support/schema.rb')
|
127
126
|
change_context
|
128
127
|
|
@@ -22,12 +22,19 @@ describe Makara::ConnectionWrapper do
|
|
22
22
|
expect(subject._makara_weight).to eq(1)
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
context '#_makara_blacklisted?' do
|
26
|
+
it 'should store the blacklist status' do
|
27
|
+
expect(subject._makara_blacklisted?).to eq(false)
|
28
|
+
subject._makara_blacklist!
|
29
|
+
expect(subject._makara_blacklisted?).to eq(true)
|
30
|
+
subject._makara_whitelist!
|
31
|
+
expect(subject._makara_blacklisted?).to eq(false)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should handle frozen pre-epoch dates' do
|
35
|
+
Timecop.freeze(Date.new(1900)) do
|
36
|
+
expect(subject._makara_blacklisted?).to eq(false)
|
37
|
+
end
|
38
|
+
end
|
31
39
|
end
|
32
|
-
|
33
40
|
end
|
data/spec/context_spec.rb
CHANGED
@@ -101,7 +101,46 @@ describe Makara::Context do
|
|
101
101
|
threads.map(&:join)
|
102
102
|
expect(uniq_curret_contexts.uniq.count).to eq(3)
|
103
103
|
end
|
104
|
+
|
105
|
+
it 'clears config sticky cache' do
|
106
|
+
Makara::Cache.store = :memory
|
107
|
+
|
108
|
+
Makara::Context.set_previous('a')
|
109
|
+
Makara::Context.stick('a', 1, 10)
|
110
|
+
expect(Makara::Context.previously_stuck?(1)).to be_truthy
|
111
|
+
|
112
|
+
Makara::Context.set_previous('b')
|
113
|
+
expect(Makara::Context.previously_stuck?(1)).to be_falsey
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe 'stick' do
|
118
|
+
it 'sticks a config to master for subsequent requests' do
|
119
|
+
Makara::Cache.store = :memory
|
120
|
+
|
121
|
+
expect(Makara::Context.stuck?('context', 1)).to be_falsey
|
122
|
+
|
123
|
+
Makara::Context.stick('context', 1, 10)
|
124
|
+
expect(Makara::Context.stuck?('context', 1)).to be_truthy
|
125
|
+
expect(Makara::Context.stuck?('context', 2)).to be_falsey
|
126
|
+
end
|
104
127
|
end
|
105
128
|
|
129
|
+
describe 'previously_stuck?' do
|
130
|
+
it 'checks whether a config was stuck to master in the previous context' do
|
131
|
+
Makara::Cache.store = :memory
|
132
|
+
Makara::Context.set_previous 'previous'
|
133
|
+
|
134
|
+
# Emulate sticking the previous web request to master.
|
135
|
+
Makara::Context.stick 'previous', 1, 10
|
136
|
+
|
137
|
+
# Emulate handling the subsequent web request with a previous context
|
138
|
+
# cookie that is stuck to master.
|
139
|
+
expect(Makara::Context.previously_stuck?(1)).to be_truthy
|
140
|
+
|
141
|
+
# Other configs should not be stuck to master, though.
|
142
|
+
expect(Makara::Context.previously_stuck?(2)).to be_falsey
|
143
|
+
end
|
144
|
+
end
|
106
145
|
end
|
107
146
|
|
data/spec/middleware_spec.rb
CHANGED
@@ -11,7 +11,7 @@ describe Makara::Middleware do
|
|
11
11
|
|
12
12
|
let(:env){ {} }
|
13
13
|
let(:proxy){ FakeProxy.new(config(1,2)) }
|
14
|
-
let(:middleware){ described_class.new(app) }
|
14
|
+
let(:middleware){ described_class.new(app, :secure => true) }
|
15
15
|
|
16
16
|
let(:key){ Makara::Middleware::IDENTIFIER }
|
17
17
|
|
@@ -56,7 +56,7 @@ describe Makara::Middleware do
|
|
56
56
|
|
57
57
|
status, headers, body = middleware.call(env)
|
58
58
|
|
59
|
-
expect(headers['Set-Cookie']).to eq("#{key}=#{Makara::Context.get_current}--200; path=/; max-age=5; HttpOnly")
|
59
|
+
expect(headers['Set-Cookie']).to eq("#{key}=#{Makara::Context.get_current}--200; path=/; max-age=5; secure; HttpOnly")
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'should preserve the same context if the previous request was a redirect' do
|
data/spec/spec_helper.rb
CHANGED
@@ -19,13 +19,13 @@ RSpec.configure do |config|
|
|
19
19
|
|
20
20
|
config.order = 'random'
|
21
21
|
|
22
|
+
require "#{File.dirname(__FILE__)}/support/helpers"
|
22
23
|
require "#{File.dirname(__FILE__)}/support/proxy_extensions"
|
23
24
|
require "#{File.dirname(__FILE__)}/support/pool_extensions"
|
24
|
-
require "#{File.dirname(__FILE__)}/support/configurator"
|
25
25
|
require "#{File.dirname(__FILE__)}/support/mock_objects"
|
26
26
|
require "#{File.dirname(__FILE__)}/support/deep_dup"
|
27
27
|
|
28
|
-
config.include
|
28
|
+
config.include SpecHelpers
|
29
29
|
|
30
30
|
config.before :each do
|
31
31
|
Makara::Cache.store = :memory
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SpecHelpers
|
2
|
+
def establish_connection(config)
|
3
|
+
connection = ActiveRecord::Base.establish_connection(config)
|
4
|
+
|
5
|
+
# make sure these are all reset to not be blacklisted
|
6
|
+
ActiveRecord::Base.connection.slave_pool.connections.each(&:_makara_whitelist!)
|
7
|
+
ActiveRecord::Base.connection.master_pool.connections.each(&:_makara_whitelist!)
|
8
|
+
|
9
|
+
ActiveRecord::Base.connection
|
10
|
+
end
|
11
|
+
|
12
|
+
def config(masters = 1, slaves = 2)
|
13
|
+
connections = []
|
14
|
+
masters.times{ connections << {:role => 'master'} }
|
15
|
+
slaves.times{ connections << {:role => 'slave'} }
|
16
|
+
{
|
17
|
+
:makara => {
|
18
|
+
:blacklist_duration => 30,
|
19
|
+
:connections => connections
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
data/spec/support/schema.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: makara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Nelson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -34,19 +34,21 @@ files:
|
|
34
34
|
- ".gitignore"
|
35
35
|
- ".rspec"
|
36
36
|
- ".ruby-gemset"
|
37
|
-
- ".ruby-version"
|
38
37
|
- ".travis.yml"
|
39
38
|
- CHANGELOG.md
|
40
39
|
- Gemfile
|
41
40
|
- LICENSE.txt
|
42
41
|
- README.md
|
43
42
|
- Rakefile
|
43
|
+
- gemfiles/ar-head.gemfile
|
44
44
|
- gemfiles/ar30.gemfile
|
45
45
|
- gemfiles/ar31.gemfile
|
46
46
|
- gemfiles/ar32.gemfile
|
47
47
|
- gemfiles/ar40.gemfile
|
48
48
|
- gemfiles/ar41.gemfile
|
49
49
|
- gemfiles/ar42.gemfile
|
50
|
+
- gemfiles/ar50.gemfile
|
51
|
+
- gemfiles/ar51.gemfile
|
50
52
|
- lib/active_record/connection_adapters/jdbcmysql_makara_adapter.rb
|
51
53
|
- lib/active_record/connection_adapters/jdbcpostgresql_makara_adapter.rb
|
52
54
|
- lib/active_record/connection_adapters/makara_abstract_adapter.rb
|
@@ -66,6 +68,7 @@ files:
|
|
66
68
|
- lib/makara/error_handler.rb
|
67
69
|
- lib/makara/errors/all_connections_blacklisted.rb
|
68
70
|
- lib/makara/errors/blacklist_connection.rb
|
71
|
+
- lib/makara/errors/makara_error.rb
|
69
72
|
- lib/makara/errors/no_connections_available.rb
|
70
73
|
- lib/makara/logging/logger.rb
|
71
74
|
- lib/makara/logging/subscriber.rb
|
@@ -92,8 +95,8 @@ files:
|
|
92
95
|
- spec/spec_helper.rb
|
93
96
|
- spec/strategies/priority_failover_spec.rb
|
94
97
|
- spec/strategies/round_robin_spec.rb
|
95
|
-
- spec/support/configurator.rb
|
96
98
|
- spec/support/deep_dup.rb
|
99
|
+
- spec/support/helpers.rb
|
97
100
|
- spec/support/mock_objects.rb
|
98
101
|
- spec/support/mysql2_database.yml
|
99
102
|
- spec/support/mysql2_database_with_custom_errors.yml
|
@@ -120,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
123
|
version: '0'
|
121
124
|
requirements: []
|
122
125
|
rubyforge_project:
|
123
|
-
rubygems_version: 2.
|
126
|
+
rubygems_version: 2.5.2
|
124
127
|
signing_key:
|
125
128
|
specification_version: 4
|
126
129
|
summary: Read-write split your DB yo
|
@@ -139,8 +142,8 @@ test_files:
|
|
139
142
|
- spec/spec_helper.rb
|
140
143
|
- spec/strategies/priority_failover_spec.rb
|
141
144
|
- spec/strategies/round_robin_spec.rb
|
142
|
-
- spec/support/configurator.rb
|
143
145
|
- spec/support/deep_dup.rb
|
146
|
+
- spec/support/helpers.rb
|
144
147
|
- spec/support/mock_objects.rb
|
145
148
|
- spec/support/mysql2_database.yml
|
146
149
|
- spec/support/mysql2_database_with_custom_errors.yml
|
@@ -148,4 +151,3 @@ test_files:
|
|
148
151
|
- spec/support/postgresql_database.yml
|
149
152
|
- spec/support/proxy_extensions.rb
|
150
153
|
- spec/support/schema.rb
|
151
|
-
has_rdoc:
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
2.1.5
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module Configurator
|
2
|
-
def config(masters = 1, slaves = 2)
|
3
|
-
connections = []
|
4
|
-
masters.times{ connections << {:role => 'master'} }
|
5
|
-
slaves.times{ connections << {:role => 'slave'} }
|
6
|
-
{
|
7
|
-
:makara => {
|
8
|
-
:blacklist_duration => 30,
|
9
|
-
:connections => connections
|
10
|
-
}
|
11
|
-
}
|
12
|
-
end
|
13
|
-
end
|