slavery 2.1.0 → 2.1.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/README.md +15 -1
- data/bin/console +3 -0
- data/lib/slavery/base.rb +2 -2
- data/lib/slavery/transaction.rb +20 -9
- data/lib/slavery/version.rb +1 -1
- data/spec/active_record/log_subscriber_spec.rb +2 -1
- data/spec/configuration_spec.rb +55 -0
- data/spec/slavery_spec.rb +0 -54
- data/spec/spec_helper.rb +37 -14
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02a75efbc26dd3232de851d07d1903f8808c0afe
|
4
|
+
data.tar.gz: 1c6bea05c62d6f8806e45b2e853ea5a78e05f70b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e9f079b232c11fc516e14d849a48f8f7de7cd00149fdf8efa951340d76a10f4c0db4b337ce602d5883212f7186d531198a60bb7a33398170dd95231301f19a6
|
7
|
+
data.tar.gz: e82e262252ab96f041f5e47766e78200e0845ba0af7983910cb6b833d0af743be6525e04bb0c7cfad0c8e0d5ed045c083aa602fd4a392c2a16ea5df5c55f6175
|
data/README.md
CHANGED
@@ -123,13 +123,27 @@ It is a good idea to confirm this behavior in your test code as well.
|
|
123
123
|
You can quickly disable slave reads by dropping the following line in `config/initializers/slavery.rb`.
|
124
124
|
|
125
125
|
```ruby
|
126
|
-
|
126
|
+
Slavery.disabled = true
|
127
127
|
```
|
128
128
|
|
129
129
|
With this line, Slavery stops connection switching and all queries go to the master.
|
130
130
|
|
131
131
|
This may be useful when one of the master or the slave goes down. You would rewrite `database.yml` to make all queries go to the surviving database, until you restore or rebuild the failed one.
|
132
132
|
|
133
|
+
## Transactional fixtures
|
134
|
+
|
135
|
+
When `use_transactional_fixtures` is set to `true`, it's NOT recommended to
|
136
|
+
write to the database besides fixtures, since the slave connection is not aware
|
137
|
+
of changes performed in the master connection due to [transaction isolation](https://en.wikipedia.org/wiki/Isolation_(database_systems)).
|
138
|
+
|
139
|
+
In that case, you are suggested to disable Slavery in the test environment by
|
140
|
+
putting the following in `test/test_helper.rb`
|
141
|
+
(or `spec/spec_helper.rb` for RSpec users):
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
Slavery.disabled = true
|
145
|
+
```
|
146
|
+
|
133
147
|
## Support for non-Rails apps
|
134
148
|
|
135
149
|
If you're using ActiveRecord in a non-Rails app (e.g. Sinatra), be sure to set `RACK_ENV` environment variable in the boot sequence, then:
|
data/bin/console
CHANGED
data/lib/slavery/base.rb
CHANGED
@@ -11,11 +11,11 @@ module Slavery
|
|
11
11
|
private
|
12
12
|
|
13
13
|
def decide_with(target)
|
14
|
-
raise Slavery::Error.new('on_slave cannot be used inside transaction block!') if inside_transaction?
|
15
|
-
|
16
14
|
if Slavery.disabled
|
17
15
|
:master
|
18
16
|
else
|
17
|
+
raise Slavery::Error.new('on_slave cannot be used inside transaction block!') if inside_transaction?
|
18
|
+
|
19
19
|
target
|
20
20
|
end
|
21
21
|
end
|
data/lib/slavery/transaction.rb
CHANGED
@@ -1,18 +1,29 @@
|
|
1
1
|
module Slavery
|
2
2
|
class Transaction
|
3
|
+
# The methods on ActiveSupport::TestCase which can potentially be used
|
4
|
+
# to determine if transactional fixtures are enabled
|
5
|
+
TEST_CONFIG_METHODS = [
|
6
|
+
:use_transactional_tests,
|
7
|
+
:use_transactional_fixtures
|
8
|
+
]
|
9
|
+
|
3
10
|
class << self
|
4
11
|
def base_depth
|
5
|
-
@base_depth ||=
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
else
|
12
|
-
0
|
13
|
-
end
|
12
|
+
@base_depth ||= if defined?(ActiveSupport::TestCase) &&
|
13
|
+
transactional_fixtures_enabled?
|
14
|
+
then
|
15
|
+
1
|
16
|
+
else
|
17
|
+
0
|
14
18
|
end
|
15
19
|
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def transactional_fixtures_enabled?
|
24
|
+
config = ActiveSupport::TestCase
|
25
|
+
TEST_CONFIG_METHODS.any? {|m| config.respond_to?(m) and config.send(m) }
|
26
|
+
end
|
16
27
|
end
|
17
28
|
end
|
18
29
|
end
|
data/lib/slavery/version.rb
CHANGED
@@ -10,10 +10,11 @@ describe ActiveRecord::LogSubscriber do
|
|
10
10
|
|
11
11
|
before do
|
12
12
|
ActiveRecord::Base.logger = logger
|
13
|
+
@backup_disabled = Slavery.disabled
|
13
14
|
end
|
14
15
|
|
15
16
|
after do
|
16
|
-
Slavery.disabled =
|
17
|
+
Slavery.disabled = @backup_disabled
|
17
18
|
end
|
18
19
|
|
19
20
|
it 'it prefixes log messages with master' do
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'configuration' do
|
4
|
+
before do
|
5
|
+
# Backup connection and configs
|
6
|
+
@backup_conn = Slavery.instance_variable_get :@connection_holder
|
7
|
+
@backup_config = ActiveRecord::Base.configurations.dup
|
8
|
+
@backup_disabled = Slavery.disabled
|
9
|
+
Slavery.instance_variable_set :@connection_holder, nil
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
# Restore connection and configs
|
14
|
+
Slavery.instance_variable_set :@connection_holder, @backup_conn
|
15
|
+
ActiveRecord::Base.configurations = @backup_config
|
16
|
+
Slavery.disabled = @backup_disabled
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'raises error if slave configuration not specified' do
|
20
|
+
ActiveRecord::Base.configurations['test_slave'] = nil
|
21
|
+
|
22
|
+
expect { Slavery.on_slave { User.count } }.to raise_error(Slavery::Error)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'connects to master if slave configuration not specified' do
|
26
|
+
ActiveRecord::Base.configurations['test_slave'] = nil
|
27
|
+
Slavery.disabled = true
|
28
|
+
|
29
|
+
expect(Slavery.on_slave { User.count }).to be 2
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'connects to slave when specified as a hash' do
|
33
|
+
Slavery.spec_key = 'test_slave'
|
34
|
+
hash = ActiveRecord::Base.configurations['test_slave']
|
35
|
+
expect(Slavery::ConnectionHolder).to receive(:establish_connection).with(hash)
|
36
|
+
Slavery::ConnectionHolder.activate
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'connects to slave when specified as a url' do
|
40
|
+
expected = if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new('4.1.0')
|
41
|
+
'postgres://root:@localhost:5432/test_slave'
|
42
|
+
else
|
43
|
+
{
|
44
|
+
'adapter' => 'postgresql',
|
45
|
+
'username' => 'root',
|
46
|
+
'host' => 'localhost',
|
47
|
+
'port' => 5432,
|
48
|
+
'database' => 'test_slave'
|
49
|
+
}
|
50
|
+
end
|
51
|
+
Slavery.spec_key = 'test_slave_url'
|
52
|
+
expect(Slavery::ConnectionHolder).to receive(:establish_connection).with(expected)
|
53
|
+
Slavery::ConnectionHolder.activate
|
54
|
+
end
|
55
|
+
end
|
data/spec/slavery_spec.rb
CHANGED
@@ -91,58 +91,4 @@ describe Slavery do
|
|
91
91
|
expect(User.where(nil).to_a.size).to be 2
|
92
92
|
expect(User.on_slave.where(nil).to_a.size).to be 1
|
93
93
|
end
|
94
|
-
|
95
|
-
describe 'configuration' do
|
96
|
-
before do
|
97
|
-
# Backup connection and configs
|
98
|
-
@backup_conn = Slavery.instance_variable_get :@connection_holder
|
99
|
-
@backup_config = ActiveRecord::Base.configurations.dup
|
100
|
-
@backup_disabled = Slavery.disabled
|
101
|
-
Slavery.instance_variable_set :@connection_holder, nil
|
102
|
-
end
|
103
|
-
|
104
|
-
after do
|
105
|
-
# Restore connection and configs
|
106
|
-
Slavery.instance_variable_set :@connection_holder, @backup_conn
|
107
|
-
ActiveRecord::Base.configurations = @backup_config
|
108
|
-
Slavery.disabled = @backup_disabled
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'raises error if slave configuration not specified' do
|
112
|
-
ActiveRecord::Base.configurations['test_slave'] = nil
|
113
|
-
|
114
|
-
expect { Slavery.on_slave { User.count } }.to raise_error(Slavery::Error)
|
115
|
-
end
|
116
|
-
|
117
|
-
it 'connects to master if slave configuration not specified' do
|
118
|
-
ActiveRecord::Base.configurations['test_slave'] = nil
|
119
|
-
Slavery.disabled = true
|
120
|
-
|
121
|
-
expect(Slavery.on_slave { User.count }).to be 2
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'connects to slave when specified as a hash' do
|
125
|
-
Slavery.spec_key = 'test_slave'
|
126
|
-
hash = ActiveRecord::Base.configurations['test_slave']
|
127
|
-
expect(Slavery::ConnectionHolder).to receive(:establish_connection).with(hash)
|
128
|
-
Slavery::ConnectionHolder.activate
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'connects to slave when specified as a url' do
|
132
|
-
expected = if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new('4.1.0')
|
133
|
-
'postgres://root:@localhost:5432/test_slave'
|
134
|
-
else
|
135
|
-
{
|
136
|
-
'adapter' => 'postgresql',
|
137
|
-
'username' => 'root',
|
138
|
-
'port' => 5432,
|
139
|
-
'database' => 'test_slave',
|
140
|
-
'host' => 'localhost'
|
141
|
-
}
|
142
|
-
end
|
143
|
-
Slavery.spec_key = 'test_slave_url'
|
144
|
-
expect(Slavery::ConnectionHolder).to receive(:establish_connection).with(expected)
|
145
|
-
Slavery::ConnectionHolder.activate
|
146
|
-
end
|
147
|
-
end
|
148
94
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -6,25 +6,48 @@ ENV['RACK_ENV'] = 'test'
|
|
6
6
|
require 'slavery'
|
7
7
|
|
8
8
|
ActiveRecord::Base.configurations = {
|
9
|
-
'test'
|
10
|
-
'test_slave'
|
11
|
-
'test_slave_url'
|
9
|
+
'test' => { 'adapter' => 'sqlite3', 'database' => 'test_db' },
|
10
|
+
'test_slave' => { 'adapter' => 'sqlite3', 'database' => 'test_slave_db' },
|
11
|
+
'test_slave_url' => 'postgres://root:@localhost:5432/test_slave'
|
12
12
|
}
|
13
13
|
|
14
14
|
# Prepare databases
|
15
15
|
class User < ActiveRecord::Base
|
16
|
+
has_many :items
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
class Item < ActiveRecord::Base
|
20
|
+
belongs_to :user
|
21
|
+
end
|
22
|
+
|
23
|
+
class Seeder
|
24
|
+
def run
|
25
|
+
# Populate on master
|
26
|
+
connect(:test)
|
27
|
+
create_tables
|
28
|
+
User.create
|
29
|
+
User.create
|
30
|
+
User.first.items.create
|
31
|
+
|
32
|
+
# Populate on slave, emulating replication lag
|
33
|
+
connect(:test_slave)
|
34
|
+
create_tables
|
35
|
+
User.create
|
23
36
|
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
|
37
|
+
# Reconnect to master
|
38
|
+
connect(:test)
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_tables
|
42
|
+
ActiveRecord::Base.connection.create_table :users, force: true
|
43
|
+
ActiveRecord::Base.connection.create_table :items, force: true do |t|
|
44
|
+
t.references :user
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def connect(env)
|
49
|
+
ActiveRecord::Base.establish_connection(env)
|
50
|
+
end
|
51
|
+
end
|
28
52
|
|
29
|
-
|
30
|
-
ActiveRecord::Base.establish_connection(:test)
|
53
|
+
Seeder.new.run
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slavery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenn Ejima
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-08-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -83,6 +83,7 @@ files:
|
|
83
83
|
- lib/slavery/version.rb
|
84
84
|
- slavery.gemspec
|
85
85
|
- spec/active_record/log_subscriber_spec.rb
|
86
|
+
- spec/configuration_spec.rb
|
86
87
|
- spec/slavery_spec.rb
|
87
88
|
- spec/spec_helper.rb
|
88
89
|
homepage: https://github.com/kenn/slavery
|
@@ -104,11 +105,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
105
|
version: '0'
|
105
106
|
requirements: []
|
106
107
|
rubyforge_project:
|
107
|
-
rubygems_version: 2.
|
108
|
+
rubygems_version: 2.6.10
|
108
109
|
signing_key:
|
109
110
|
specification_version: 4
|
110
111
|
summary: Simple, conservative slave reads for ActiveRecord
|
111
112
|
test_files:
|
112
113
|
- spec/active_record/log_subscriber_spec.rb
|
114
|
+
- spec/configuration_spec.rb
|
113
115
|
- spec/slavery_spec.rb
|
114
116
|
- spec/spec_helper.rb
|