makara 0.3.9 → 0.3.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +35 -0
- data/CHANGELOG.md +23 -1
- data/Gemfile +1 -1
- data/README.md +9 -2
- data/gemfiles/ar-head.gemfile +10 -1
- data/gemfiles/ar30.gemfile +7 -3
- data/gemfiles/ar31.gemfile +8 -3
- data/gemfiles/ar32.gemfile +8 -3
- data/gemfiles/ar40.gemfile +10 -3
- data/gemfiles/ar41.gemfile +10 -3
- data/gemfiles/ar42.gemfile +10 -3
- data/gemfiles/ar50.gemfile +10 -1
- data/gemfiles/ar51.gemfile +10 -1
- data/lib/active_record/connection_adapters/makara_abstract_adapter.rb +3 -3
- data/lib/makara/cache/memory_store.rb +4 -1
- data/lib/makara/connection_wrapper.rb +2 -2
- data/lib/makara/pool.rb +4 -7
- data/lib/makara/proxy.rb +0 -1
- data/lib/makara/strategies/round_robin.rb +6 -0
- data/lib/makara/version.rb +1 -1
- data/spec/active_record/connection_adapters/makara_abstract_adapter_spec.rb +10 -1
- data/spec/active_record/connection_adapters/makara_mysql2_adapter_spec.rb +16 -1
- data/spec/active_record/connection_adapters/makara_postgis_adapter_spec.rb +10 -5
- data/spec/active_record/connection_adapters/makara_postgresql_adapter_spec.rb +17 -1
- data/spec/cache_spec.rb +22 -0
- data/spec/connection_wrapper_spec.rb +5 -2
- data/spec/spec_helper.rb +2 -0
- data/spec/support/mysql2_database.yml +1 -0
- data/spec/support/mysql2_database_with_custom_errors.yml +5 -0
- data/spec/support/postgis_database.yml +2 -0
- data/spec/support/postgis_schema.rb +6 -3
- data/spec/support/postgresql_database.yml +2 -0
- data/spec/support/schema.rb +5 -5
- data/spec/support/user.rb +5 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4dc4867024ed5527a9b0a499e4daff0c9c4bac5e
|
4
|
+
data.tar.gz: 170743d2e7f735b39fbcb477657643918c66cd32
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8da212514ba19441a154323990544bb18ce0a3a39ff133f227bab84790e48b747f254b53d9a59c2aa93cfad0f0367fd03a44d3bcbe94a17874e7f2b084bec468
|
7
|
+
data.tar.gz: 731c52cd786a65d0a124edf94e1f721b69ec78cee0549d499b2cc35a5ac2210aa7ae87d8b22a3734829271ea538ed6b3cfb197fd1ebc2d4ce0f961d16e86afda
|
data/.travis.yml
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
cache: bundler
|
4
|
+
dist: precise
|
4
5
|
|
5
6
|
services:
|
6
7
|
- mysql
|
7
8
|
- postgresql
|
8
9
|
|
10
|
+
before_install:
|
11
|
+
- gem install bundler
|
12
|
+
|
9
13
|
before_script:
|
10
14
|
- mysql -e 'create database makara_test;'
|
11
15
|
- psql -c 'create database makara_test;' -U postgres
|
@@ -17,6 +21,7 @@ rvm:
|
|
17
21
|
- 2.2
|
18
22
|
- 2.3
|
19
23
|
- 2.4
|
24
|
+
- 2.5.0
|
20
25
|
- ruby-head
|
21
26
|
- jruby
|
22
27
|
|
@@ -43,8 +48,34 @@ matrix:
|
|
43
48
|
rvm: 2.3
|
44
49
|
- gemfile: gemfiles/ar30.gemfile
|
45
50
|
rvm: 2.4
|
51
|
+
- gemfile: gemfiles/ar31.gemfile
|
52
|
+
rvm: 2.4
|
53
|
+
- gemfile: gemfiles/ar32.gemfile
|
54
|
+
rvm: 2.4
|
55
|
+
- gemfile: gemfiles/ar40.gemfile
|
56
|
+
rvm: 2.4
|
57
|
+
- gemfile: gemfiles/ar41.gemfile
|
58
|
+
rvm: 2.4
|
59
|
+
- gemfile: gemfiles/ar30.gemfile
|
60
|
+
rvm: 2.5.0
|
61
|
+
- gemfile: gemfiles/ar31.gemfile
|
62
|
+
rvm: 2.5.0
|
63
|
+
- gemfile: gemfiles/ar32.gemfile
|
64
|
+
rvm: 2.5.0
|
65
|
+
- gemfile: gemfiles/ar40.gemfile
|
66
|
+
rvm: 2.5.0
|
67
|
+
- gemfile: gemfiles/ar41.gemfile
|
68
|
+
rvm: 2.5.0
|
46
69
|
- gemfile: gemfiles/ar30.gemfile
|
47
70
|
rvm: ruby-head
|
71
|
+
- gemfile: gemfiles/ar31.gemfile
|
72
|
+
rvm: ruby-head
|
73
|
+
- gemfile: gemfiles/ar32.gemfile
|
74
|
+
rvm: ruby-head
|
75
|
+
- gemfile: gemfiles/ar40.gemfile
|
76
|
+
rvm: ruby-head
|
77
|
+
- gemfile: gemfiles/ar41.gemfile
|
78
|
+
rvm: ruby-head
|
48
79
|
- gemfile: gemfiles/ar50.gemfile
|
49
80
|
rvm: 2.0
|
50
81
|
- gemfile: gemfiles/ar50.gemfile
|
@@ -63,6 +94,10 @@ matrix:
|
|
63
94
|
rvm: 2.1
|
64
95
|
- gemfile: gemfiles/ar-head.gemfile
|
65
96
|
rvm: 2.2
|
97
|
+
- gemfile: gemfiles/ar-head.gemfile
|
98
|
+
rvm: 2.3
|
99
|
+
- gemfile: gemfiles/ar-head.gemfile
|
100
|
+
rvm: 2.4
|
66
101
|
allow_failures:
|
67
102
|
- gemfile: gemfiles/ar-head.gemfile
|
68
103
|
- rvm: ruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,29 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
-
## v0.3.
|
4
|
+
## v0.3.9 - 2013-03-20
|
5
|
+
[Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.9...v0.3.10)
|
6
|
+
|
7
|
+
Fixed
|
8
|
+
- Send nextval queries to master and show queries to replicas for Postgres [#173](https://github.com/taskrabbit/makara/pull/173) Andrew Kane
|
9
|
+
- Fixes can't add a new key into hash during iteration error [#174](https://github.com/taskrabbit/makara/pull/174) Andrew Kane
|
10
|
+
- Fix: an application freezes when a slave is down [#180](https://github.com/taskrabbit/makara/pull/180) Alexey P
|
11
|
+
- Allow SELECTs that use common table expressions to go to replicas [#184](https://github.com/taskrabbit/makara/pull/184) Andrew Kane
|
12
|
+
- Send advisory lock requests to the master [#198](https://github.com/taskrabbit/makara/pull/198) George Claghorn
|
13
|
+
- Postgres exists query [#199](https://github.com/taskrabbit/makara/pull/199) Brian Leonard
|
14
|
+
|
15
|
+
Documentation and Test
|
16
|
+
- Clarify README's "What goes where" [#187](https://github.com/taskrabbit/makara/pull/187) Jan Sandbrink
|
17
|
+
- Fix loading fixtures in Rails 5.2 [#192](https://github.com/taskrabbit/makara/pull/192) George Claghorn
|
18
|
+
- Travis Upgrade [#199](https://github.com/taskrabbit/makara/pull/199) Brian Leonard
|
19
|
+
|
20
|
+
## v0.3.9 - 2017-08-14
|
21
|
+
[Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.8...v0.3.9)
|
22
|
+
|
23
|
+
Changed
|
24
|
+
- Add postgis support [#118](https://github.com/taskrabbit/makara/pull/118) Kevin Bacha
|
25
|
+
|
26
|
+
## v0.3.8 - 2017-07-11
|
5
27
|
|
6
28
|
[Full Changelog](https://github.com/taskrabbit/makara/compare/v0.3.7...v0.3.8)
|
7
29
|
|
data/Gemfile
CHANGED
@@ -11,7 +11,7 @@ gem 'ruby-debug', :platform => :jruby
|
|
11
11
|
gem 'rack', '1.6.0'
|
12
12
|
|
13
13
|
gem 'mysql2', :platform => :ruby
|
14
|
-
gem 'pg', :platform => :ruby
|
14
|
+
gem 'pg', '0.21.0', :platform => :ruby
|
15
15
|
gem 'activerecord-postgis-adapter', :platform => :ruby
|
16
16
|
gem 'rgeo', :platform => :ruby
|
17
17
|
|
data/README.md
CHANGED
@@ -120,7 +120,13 @@ By creating a makara database adapter which simply acts as a proxy we avoid any
|
|
120
120
|
|
121
121
|
### What goes where?
|
122
122
|
|
123
|
-
Any `SELECT` statements will execute against your slave(s), anything else will go to master.
|
123
|
+
In general: Any `SELECT` statements will execute against your slave(s), anything else will go to master.
|
124
|
+
|
125
|
+
There are some edge cases:
|
126
|
+
* `SET` operations will be sent to all connections
|
127
|
+
* Execution of specific methods such as `connect!`, `disconnect!`, and `clear_cache!` are invoked on all underlying connections
|
128
|
+
* Calls inside a transaction will always be sent to the master (otherwise changes from within the transaction could not be read back on most transaction isolation levels)
|
129
|
+
* Locking reads (e.g. `SELECT ... FOR UPDATE`) will always be sent to the master
|
124
130
|
|
125
131
|
### Errors / blacklisting
|
126
132
|
|
@@ -165,7 +171,8 @@ The makara subconfig sets up the proxy with a few of its own options, then provi
|
|
165
171
|
* disable_blacklist - do not blacklist node at any error, useful in case of one master
|
166
172
|
* sticky - if a node should be stuck to once it's used during a specific context
|
167
173
|
* master_ttl - how long the master context is persisted. generally, this needs to be longer than any replication lag
|
168
|
-
* master_strategy - use a different strategy for picking the "current" node: `failover` will try to keep the same one until it is blacklisted. The default is `round_robin` which will cycle through available ones.
|
174
|
+
* master_strategy - use a different strategy for picking the "current" master node: `failover` will try to keep the same one until it is blacklisted. The default is `round_robin` which will cycle through available ones.
|
175
|
+
* slave_strategy - use a different strategy for picking the "current" slave node: `failover` will try to keep the same one until it is blacklisted. The default is `round_robin` which will cycle through available ones.
|
169
176
|
* connection_error_matchers - array of custom error matchers you want to be handled gracefully by Makara (as in, errors matching these regexes will result in blacklisting the connection as opposed to raising directly).
|
170
177
|
|
171
178
|
Connection definitions contain any extra node-specific configurations. If the node should behave as a master you must provide `role: master`. Any previous configurations can be overridden within a specific node's config. Nodes can also contain weights if you'd like to balance usage based on hardware specifications. Optionally, you can provide a name attribute which will be used in sql logging.
|
data/gemfiles/ar-head.gemfile
CHANGED
@@ -11,5 +11,14 @@ gem 'rack'
|
|
11
11
|
gem 'timecop'
|
12
12
|
gem 'mysql2', :platform => :ruby
|
13
13
|
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
|
-
gem 'pg', :platform => :ruby
|
14
|
+
gem 'pg', '0.21.0', :platform => :ruby
|
15
15
|
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
16
|
+
|
17
|
+
|
18
|
+
rmajor, rminor, rpatch = RUBY_VERSION.split(/[^\d]/)[0..2].map(&:to_i)
|
19
|
+
|
20
|
+
# 2.1 +
|
21
|
+
if rmajor > 2 || (rmajor == 2 && rminor >= 1)
|
22
|
+
gem 'activerecord-postgis-adapter', :platform => :ruby
|
23
|
+
gem 'rgeo', :platform => :ruby
|
24
|
+
end
|
data/gemfiles/ar30.gemfile
CHANGED
@@ -12,8 +12,6 @@ gem 'i18n', '~> 0.5.0'
|
|
12
12
|
gem 'mysql2', '0.2.11', :platform => :ruby
|
13
13
|
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
14
|
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
15
|
-
gem 'activerecord-postgis-adapter', :platform => :ruby
|
16
|
-
gem 'rgeo', :platform => :ruby
|
17
15
|
|
18
16
|
|
19
17
|
rmajor, rminor, rpatch = RUBY_VERSION.split(/[^\d]/)[0..2].map(&:to_i)
|
@@ -28,5 +26,11 @@ end
|
|
28
26
|
if rmajor == 1 && (rminor == 8 || (rminor == 9 && rpatch < 3))
|
29
27
|
gem 'pg', '0.17.1', :platform => :ruby
|
30
28
|
else
|
31
|
-
gem 'pg', :platform => :ruby
|
29
|
+
gem 'pg', '0.21.0', :platform => :ruby
|
30
|
+
end
|
31
|
+
|
32
|
+
# 2.1 +
|
33
|
+
if rmajor > 2 || (rmajor == 2 && rminor >= 1)
|
34
|
+
gem 'activerecord-postgis-adapter', :platform => :ruby
|
35
|
+
gem 'rgeo', :platform => :ruby
|
32
36
|
end
|
data/gemfiles/ar31.gemfile
CHANGED
@@ -12,8 +12,7 @@ gem 'i18n', '~> 0.6.0'
|
|
12
12
|
gem 'mysql2', '~> 0.3.10', :platform => :ruby
|
13
13
|
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
14
|
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
15
|
-
|
16
|
-
gem 'rgeo', :platform => :ruby
|
15
|
+
|
17
16
|
|
18
17
|
rmajor, rminor, rpatch = RUBY_VERSION.split(/[^\d]/)[0..2].map(&:to_i)
|
19
18
|
|
@@ -27,5 +26,11 @@ end
|
|
27
26
|
if rmajor == 1 && (rminor == 8 || (rminor == 9 && rpatch < 3))
|
28
27
|
gem 'pg', '0.17.1', :platform => :ruby
|
29
28
|
else
|
30
|
-
gem 'pg', :platform => :ruby
|
29
|
+
gem 'pg', '0.21.0', :platform => :ruby
|
30
|
+
end
|
31
|
+
|
32
|
+
# 2.1 +
|
33
|
+
if rmajor > 2 || (rmajor == 2 && rminor >= 1)
|
34
|
+
gem 'activerecord-postgis-adapter', :platform => :ruby
|
35
|
+
gem 'rgeo', :platform => :ruby
|
31
36
|
end
|
data/gemfiles/ar32.gemfile
CHANGED
@@ -12,8 +12,7 @@ gem 'i18n', '~> 0.6.0'
|
|
12
12
|
gem 'mysql2', '~> 0.3.10', :platform => :ruby
|
13
13
|
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
14
|
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
15
|
-
|
16
|
-
gem 'rgeo', :platform => :ruby
|
15
|
+
|
17
16
|
|
18
17
|
rmajor, rminor, rpatch = RUBY_VERSION.split(/[^\d]/)[0..2].map(&:to_i)
|
19
18
|
|
@@ -27,5 +26,11 @@ end
|
|
27
26
|
if rmajor == 1 && (rminor == 8 || (rminor == 9 && rpatch < 3))
|
28
27
|
gem 'pg', '0.17.1', :platform => :ruby
|
29
28
|
else
|
30
|
-
gem 'pg', :platform => :ruby
|
29
|
+
gem 'pg', '0.21.0', :platform => :ruby
|
30
|
+
end
|
31
|
+
|
32
|
+
# 2.1 +
|
33
|
+
if rmajor > 2 || (rmajor == 2 && rminor >= 1)
|
34
|
+
gem 'activerecord-postgis-adapter', :platform => :ruby
|
35
|
+
gem 'rgeo', :platform => :ruby
|
31
36
|
end
|
data/gemfiles/ar40.gemfile
CHANGED
@@ -11,7 +11,14 @@ gem 'rack', '1.6.0'
|
|
11
11
|
gem 'timecop'
|
12
12
|
gem 'mysql2', '~> 0.3.10', :platform => :ruby
|
13
13
|
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
|
-
gem 'pg', :platform => :ruby
|
14
|
+
gem 'pg', '0.21.0', :platform => :ruby
|
15
15
|
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
16
|
-
|
17
|
-
|
16
|
+
|
17
|
+
|
18
|
+
rmajor, rminor, rpatch = RUBY_VERSION.split(/[^\d]/)[0..2].map(&:to_i)
|
19
|
+
|
20
|
+
# 2.1 +
|
21
|
+
if rmajor > 2 || (rmajor == 2 && rminor >= 1)
|
22
|
+
gem 'activerecord-postgis-adapter', :platform => :ruby
|
23
|
+
gem 'rgeo', :platform => :ruby
|
24
|
+
end
|
data/gemfiles/ar41.gemfile
CHANGED
@@ -11,7 +11,14 @@ gem 'rack', '1.6.0'
|
|
11
11
|
gem 'timecop'
|
12
12
|
gem 'mysql2', '~> 0.3.10', :platform => :ruby
|
13
13
|
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
|
-
gem 'pg', :platform => :ruby
|
14
|
+
gem 'pg', '0.21.0', :platform => :ruby
|
15
15
|
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
16
|
-
|
17
|
-
|
16
|
+
|
17
|
+
|
18
|
+
rmajor, rminor, rpatch = RUBY_VERSION.split(/[^\d]/)[0..2].map(&:to_i)
|
19
|
+
|
20
|
+
# 2.1 +
|
21
|
+
if rmajor > 2 || (rmajor == 2 && rminor >= 1)
|
22
|
+
gem 'activerecord-postgis-adapter', :platform => :ruby
|
23
|
+
gem 'rgeo', :platform => :ruby
|
24
|
+
end
|
data/gemfiles/ar42.gemfile
CHANGED
@@ -11,7 +11,14 @@ gem 'rack', '1.6.0'
|
|
11
11
|
gem 'timecop'
|
12
12
|
gem 'mysql2', '~> 0.3.10', :platform => :ruby
|
13
13
|
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
|
-
gem 'pg', :platform => :ruby
|
14
|
+
gem 'pg', '0.21.0', :platform => :ruby
|
15
15
|
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
16
|
-
|
17
|
-
|
16
|
+
|
17
|
+
|
18
|
+
rmajor, rminor, rpatch = RUBY_VERSION.split(/[^\d]/)[0..2].map(&:to_i)
|
19
|
+
|
20
|
+
# 2.1 +
|
21
|
+
if rmajor > 2 || (rmajor == 2 && rminor >= 1)
|
22
|
+
gem 'activerecord-postgis-adapter', :platform => :ruby
|
23
|
+
gem 'rgeo', :platform => :ruby
|
24
|
+
end
|
data/gemfiles/ar50.gemfile
CHANGED
@@ -11,5 +11,14 @@ gem 'rack'
|
|
11
11
|
gem 'timecop'
|
12
12
|
gem 'mysql2', :platform => :ruby
|
13
13
|
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
|
-
gem 'pg', :platform => :ruby
|
14
|
+
gem 'pg', '0.21.0', :platform => :ruby
|
15
15
|
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
16
|
+
|
17
|
+
|
18
|
+
rmajor, rminor, rpatch = RUBY_VERSION.split(/[^\d]/)[0..2].map(&:to_i)
|
19
|
+
|
20
|
+
# 2.1 +
|
21
|
+
if rmajor > 2 || (rmajor == 2 && rminor >= 1)
|
22
|
+
gem 'activerecord-postgis-adapter', :platform => :ruby
|
23
|
+
gem 'rgeo', :platform => :ruby
|
24
|
+
end
|
data/gemfiles/ar51.gemfile
CHANGED
@@ -11,5 +11,14 @@ gem 'rack'
|
|
11
11
|
gem 'timecop'
|
12
12
|
gem 'mysql2', :platform => :ruby
|
13
13
|
gem 'activerecord-jdbcmysql-adapter', :platform => :jruby
|
14
|
-
gem 'pg', :platform => :ruby
|
14
|
+
gem 'pg', '0.21.0', :platform => :ruby
|
15
15
|
gem 'activerecord-jdbcpostgresql-adapter', :platform => :jruby
|
16
|
+
|
17
|
+
|
18
|
+
rmajor, rminor, rpatch = RUBY_VERSION.split(/[^\d]/)[0..2].map(&:to_i)
|
19
|
+
|
20
|
+
# 2.1 +
|
21
|
+
if rmajor > 2 || (rmajor == 2 && rminor >= 1)
|
22
|
+
gem 'activerecord-postgis-adapter', :platform => :ruby
|
23
|
+
gem 'rgeo', :platform => :ruby
|
24
|
+
end
|
@@ -105,11 +105,11 @@ module ActiveRecord
|
|
105
105
|
end
|
106
106
|
|
107
107
|
|
108
|
-
hijack_method :execute, :
|
108
|
+
hijack_method :execute, :exec_query, :exec_no_cache, :exec_cache, :transaction
|
109
109
|
send_to_all :connect, :reconnect!, :verify!, :clear_cache!, :reset!
|
110
110
|
|
111
|
-
SQL_MASTER_MATCHERS = [/\A\s*select.+for update\Z/i, /select.+lock in share mode\Z/i].map(&:freeze).freeze
|
112
|
-
SQL_SLAVE_MATCHERS = [/\A\s*select\s/i].map(&:freeze).freeze
|
111
|
+
SQL_MASTER_MATCHERS = [/\A\s*select.+for update\Z/i, /select.+lock in share mode\Z/i, /\A\s*select.+(nextval|currval|lastval|get_lock|release_lock|pg_advisory_lock|pg_advisory_unlock)\(/i].map(&:freeze).freeze
|
112
|
+
SQL_SLAVE_MATCHERS = [/\A\s*(select|with.+\)\s*select)\s/i].map(&:freeze).freeze
|
113
113
|
SQL_ALL_MATCHERS = [/\A\s*set\s/i].map(&:freeze).freeze
|
114
114
|
SQL_SKIP_STICKINESS_MATCHERS = [/\A\s*show\s([\w]+\s)?(field|table|database|schema|view|index)(es|s)?/i, /\A\s*(set|describe|explain|pragma)\s/i].map(&:freeze).freeze
|
115
115
|
|
@@ -4,6 +4,7 @@ module Makara
|
|
4
4
|
|
5
5
|
def initialize
|
6
6
|
@data = {}
|
7
|
+
@mutex = Mutex.new
|
7
8
|
end
|
8
9
|
|
9
10
|
def read(key)
|
@@ -20,7 +21,9 @@ module Makara
|
|
20
21
|
protected
|
21
22
|
|
22
23
|
def clean
|
23
|
-
@
|
24
|
+
@mutex.synchronize do
|
25
|
+
@data.delete_if{|k,v| v[1] <= Time.now.to_i }
|
26
|
+
end
|
24
27
|
end
|
25
28
|
|
26
29
|
end
|
@@ -146,10 +146,10 @@ module Makara
|
|
146
146
|
# The new definition should allow for the proxy to intercept the invocation if required.
|
147
147
|
@proxy.class.hijack_methods.each do |meth|
|
148
148
|
extension << %Q{
|
149
|
-
def #{meth}(*args)
|
149
|
+
def #{meth}(*args, &block)
|
150
150
|
_makara_hijack do |proxy|
|
151
151
|
if proxy
|
152
|
-
proxy.#{meth}(*args)
|
152
|
+
proxy.#{meth}(*args, &block)
|
153
153
|
else
|
154
154
|
super
|
155
155
|
end
|
data/lib/makara/pool.rb
CHANGED
@@ -64,17 +64,14 @@ module Makara
|
|
64
64
|
@connections.each do |con|
|
65
65
|
next if con._makara_blacklisted?
|
66
66
|
begin
|
67
|
-
|
68
|
-
|
67
|
+
ret = @proxy.error_handler.handle(con) do
|
68
|
+
if block
|
69
69
|
yield con
|
70
|
+
else
|
71
|
+
con.send(method, *args)
|
70
72
|
end
|
71
73
|
end
|
72
74
|
|
73
|
-
if method
|
74
|
-
ret = con.send(method, *args)
|
75
|
-
else
|
76
|
-
ret = value
|
77
|
-
end
|
78
75
|
one_worked = true
|
79
76
|
rescue Makara::Errors::BlacklistConnection => e
|
80
77
|
errors.insert(0, e)
|
data/lib/makara/proxy.rb
CHANGED
@@ -23,6 +23,8 @@ module Makara
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def next
|
26
|
+
return safe_value(0, true) if single_one?
|
27
|
+
|
26
28
|
idx = @current_idx
|
27
29
|
begin
|
28
30
|
|
@@ -67,6 +69,10 @@ module Makara
|
|
67
69
|
def should_shuffle?
|
68
70
|
true
|
69
71
|
end
|
72
|
+
|
73
|
+
def single_one?
|
74
|
+
false
|
75
|
+
end
|
70
76
|
end
|
71
77
|
end
|
72
78
|
end
|
data/lib/makara/version.rb
CHANGED
@@ -27,7 +27,16 @@ describe ActiveRecord::ConnectionAdapters::MakaraAbstractAdapter do
|
|
27
27
|
' select * from users for update' => true,
|
28
28
|
'select * from users lock in share mode' => true,
|
29
29
|
'select * from users where name = "for update"' => false,
|
30
|
-
'select * from users where name = "lock in share mode"' => false
|
30
|
+
'select * from users where name = "lock in share mode"' => false,
|
31
|
+
'select nextval(\'users_id_seq\')' => true,
|
32
|
+
'select currval(\'users_id_seq\')' => true,
|
33
|
+
'select lastval()' => true,
|
34
|
+
'with fence as (select * from users) select * from fence' => false,
|
35
|
+
'with fence as (select * from felines) insert to cats' => true,
|
36
|
+
'select get_lock(\'foo\', 0)' => true,
|
37
|
+
'select release_lock(\'foo\')' => true,
|
38
|
+
'select pg_advisory_lock(12345)' => true,
|
39
|
+
'select pg_advisory_unlock(12345)' => true
|
31
40
|
}.each do |sql, should_go_to_master|
|
32
41
|
|
33
42
|
it "determines that \"#{sql}\" #{should_go_to_master ? 'requires' : 'does not require'} master" do
|
@@ -150,7 +150,7 @@ describe 'MakaraMysql2Adapter' do
|
|
150
150
|
|
151
151
|
it 'should send reads to the slave' do
|
152
152
|
# ensure the next connection will be the first one
|
153
|
-
|
153
|
+
allow_any_instance_of(Makara::Strategies::RoundRobin).to receive(:single_one?){ true }
|
154
154
|
|
155
155
|
con = connection.slave_pool.connections.first
|
156
156
|
expect(con).to receive(:execute).with('SELECT * FROM users').once
|
@@ -158,6 +158,21 @@ describe 'MakaraMysql2Adapter' do
|
|
158
158
|
connection.execute('SELECT * FROM users')
|
159
159
|
end
|
160
160
|
|
161
|
+
it 'should send exists? to slave' do
|
162
|
+
next if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0 # query doesn't work?
|
163
|
+
|
164
|
+
allow_any_instance_of(Makara::Strategies::RoundRobin).to receive(:single_one?){ true }
|
165
|
+
Test::User.exists? # flush other (schema) things that need to happen
|
166
|
+
|
167
|
+
con = connection.slave_pool.connections.first
|
168
|
+
if (ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR <= 0)
|
169
|
+
expect(con).to receive(:execute).with(/SELECT\s+1\s*(AS one)?\s+FROM .?users.?\s+LIMIT\s+.?1/, any_args).once.and_call_original
|
170
|
+
else
|
171
|
+
expect(con).to receive(:exec_query).with(/SELECT\s+1\s*(AS one)?\s+FROM .?users.?\s+LIMIT\s+.?1/, any_args).once.and_call_original
|
172
|
+
end
|
173
|
+
Test::User.exists?
|
174
|
+
end
|
175
|
+
|
161
176
|
it 'should send writes to master' do
|
162
177
|
con = connection.master_pool.connections.first
|
163
178
|
expect(con).to receive(:execute).with('UPDATE users SET name = "bob" WHERE id = 1')
|
@@ -1,8 +1,16 @@
|
|
1
1
|
# RGeo doesn't play well with JRuby and to avoid complicated test setup
|
2
2
|
# we're only testing ActiveRecord version ~> 4.2
|
3
|
+
# also rgeo only works on 2.1+
|
4
|
+
|
5
|
+
rmajor, rminor, rpatch = RUBY_VERSION.split(/[^\d]/)[0..2].map(&:to_i)
|
6
|
+
require 'active_record'
|
7
|
+
|
8
|
+
# TODO: test this in AR 5+ ?
|
9
|
+
|
3
10
|
if RUBY_ENGINE == 'ruby' &&
|
4
11
|
ActiveRecord::VERSION::MAJOR == 4 &&
|
5
|
-
ActiveRecord::VERSION::MINOR >= 2
|
12
|
+
ActiveRecord::VERSION::MINOR >= 2 &&
|
13
|
+
(rmajor > 2 || (rmajor == 2 && rminor >= 1))
|
6
14
|
|
7
15
|
require 'spec_helper'
|
8
16
|
require 'rgeo'
|
@@ -83,10 +91,7 @@ if RUBY_ENGINE == 'ruby' &&
|
|
83
91
|
|
84
92
|
it 'should send reads to the slave' do
|
85
93
|
# ensure the next connection will be the first one
|
86
|
-
|
87
|
-
.strategy
|
88
|
-
.instance_variable_set('@current_idx',
|
89
|
-
connection.slave_pool.connections.length)
|
94
|
+
allow_any_instance_of(Makara::Strategies::RoundRobin).to receive(:single_one?){ true }
|
90
95
|
|
91
96
|
con = connection.slave_pool.connections.first
|
92
97
|
expect(con).to receive(:execute).with('SELECT * FROM users').once
|
@@ -64,7 +64,7 @@ describe 'MakaraPostgreSQLAdapter' do
|
|
64
64
|
|
65
65
|
it 'should send reads to the slave' do
|
66
66
|
# ensure the next connection will be the first one
|
67
|
-
|
67
|
+
allow_any_instance_of(Makara::Strategies::RoundRobin).to receive(:single_one?){ true }
|
68
68
|
|
69
69
|
con = connection.slave_pool.connections.first
|
70
70
|
expect(con).to receive(:execute).with('SELECT * FROM users').once
|
@@ -72,6 +72,22 @@ describe 'MakaraPostgreSQLAdapter' do
|
|
72
72
|
connection.execute('SELECT * FROM users')
|
73
73
|
end
|
74
74
|
|
75
|
+
it 'should send exists? to slave' do
|
76
|
+
next if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0 # query doesn't work?
|
77
|
+
|
78
|
+
allow_any_instance_of(Makara::Strategies::RoundRobin).to receive(:single_one?){ true }
|
79
|
+
Test::User.exists? # flush other (schema) things that need to happen
|
80
|
+
|
81
|
+
con = connection.slave_pool.connections.first
|
82
|
+
if (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR >= 2) ||
|
83
|
+
(ActiveRecord::VERSION::MAJOR == 5 && ActiveRecord::VERSION::MINOR <= 0)
|
84
|
+
expect(con).to receive(:exec_no_cache).with(/SELECT\s+1\s*(AS one)?\s+FROM .?users.?\s+LIMIT\s+.?1/, any_args).once.and_call_original
|
85
|
+
else
|
86
|
+
expect(con).to receive(:exec_query).with(/SELECT\s+1\s*(AS one)?\s+FROM .?users.?\s+LIMIT\s+.?1/, any_args).once.and_call_original
|
87
|
+
end
|
88
|
+
Test::User.exists?
|
89
|
+
end
|
90
|
+
|
75
91
|
it 'should send writes to master' do
|
76
92
|
con = connection.master_pool.connections.first
|
77
93
|
expect(con).to receive(:execute).with('UPDATE users SET name = "bob" WHERE id = 1')
|
data/spec/cache_spec.rb
CHANGED
@@ -52,6 +52,28 @@ describe Makara::Cache do
|
|
52
52
|
expect(data).not_to have_key('test')
|
53
53
|
end
|
54
54
|
|
55
|
+
it 'has thread-safety' do
|
56
|
+
store = Makara::Cache::MemoryStore.new
|
57
|
+
previous_value = Thread.abort_on_exception
|
58
|
+
|
59
|
+
begin
|
60
|
+
Thread.abort_on_exception = true
|
61
|
+
|
62
|
+
workers = 2.times.map do
|
63
|
+
Thread.new do
|
64
|
+
100.times do |n|
|
65
|
+
store.write(n, 'value', expires_in: 0.5)
|
66
|
+
sleep(0.01)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
expect { workers.map(&:join) }.to_not raise_error
|
72
|
+
ensure
|
73
|
+
Thread.abort_on_exception = previous_value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
55
77
|
end
|
56
78
|
|
57
79
|
|
@@ -14,8 +14,11 @@ describe Makara::ConnectionWrapper do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'should invoke hijacked methods on the proxy when invoked directly' do
|
17
|
-
expect(proxy).to receive(:execute).with('test').once
|
18
|
-
|
17
|
+
expect(proxy).to receive(:execute).with('test').once do |&block|
|
18
|
+
expect(block.call).to eq('Hello')
|
19
|
+
end
|
20
|
+
|
21
|
+
connection.execute('test') { 'Hello' }
|
19
22
|
end
|
20
23
|
|
21
24
|
it 'should have a default weight of 1' do
|
data/spec/spec_helper.rb
CHANGED
@@ -24,6 +24,7 @@ RSpec.configure do |config|
|
|
24
24
|
require "#{File.dirname(__FILE__)}/support/pool_extensions"
|
25
25
|
require "#{File.dirname(__FILE__)}/support/mock_objects"
|
26
26
|
require "#{File.dirname(__FILE__)}/support/deep_dup"
|
27
|
+
require "#{File.dirname(__FILE__)}/support/user"
|
27
28
|
|
28
29
|
config.include SpecHelpers
|
29
30
|
|
@@ -31,6 +32,7 @@ RSpec.configure do |config|
|
|
31
32
|
Makara::Cache.store = :memory
|
32
33
|
change_context
|
33
34
|
allow_any_instance_of(Makara::Strategies::RoundRobin).to receive(:should_shuffle?){ false }
|
35
|
+
RSpec::Mocks.space.proxy_for(ActiveRecord::Base).reset # make sure not stubbed in some way
|
34
36
|
end
|
35
37
|
|
36
38
|
def change_context
|
@@ -1,8 +1,11 @@
|
|
1
|
+
conn = ActiveRecord::Base.connection
|
1
2
|
|
2
|
-
|
3
|
-
execute "create extension if not exists postgis"
|
3
|
+
conn.execute "create extension if not exists postgis"
|
4
4
|
|
5
|
-
|
5
|
+
if conn.table_exists? "towns"
|
6
|
+
conn.execute("TRUNCATE TABLE towns")
|
7
|
+
else
|
8
|
+
conn.create_table "towns", :force => true do |t|
|
6
9
|
t.st_point "location"
|
7
10
|
end
|
8
11
|
end
|
data/spec/support/schema.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
ActiveRecord::
|
1
|
+
conn = ActiveRecord::Base.connection
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
if conn.table_exists? "users"
|
4
|
+
conn.execute("TRUNCATE TABLE users")
|
5
|
+
else
|
6
|
+
conn.create_table "users" do |t|
|
6
7
|
t.string "name"
|
7
8
|
end
|
8
|
-
|
9
9
|
end
|
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.10
|
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: 2018-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -108,6 +108,7 @@ files:
|
|
108
108
|
- spec/support/postgresql_database.yml
|
109
109
|
- spec/support/proxy_extensions.rb
|
110
110
|
- spec/support/schema.rb
|
111
|
+
- spec/support/user.rb
|
111
112
|
homepage: ''
|
112
113
|
licenses: []
|
113
114
|
metadata: {}
|
@@ -158,3 +159,4 @@ test_files:
|
|
158
159
|
- spec/support/postgresql_database.yml
|
159
160
|
- spec/support/proxy_extensions.rb
|
160
161
|
- spec/support/schema.rb
|
162
|
+
- spec/support/user.rb
|