ar-multidb 0.4.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Multidb do
6
+ let(:balancer) { instance_double('Multidb::Balancer', use: nil, get: nil, disconnect!: nil) }
7
+
8
+ describe '.balancer' do
9
+ subject { described_class.balancer }
10
+
11
+ context 'with no configuration' do
12
+ it 'raises exception' do
13
+ expect { subject }.to raise_error(Multidb::NotInitializedError)
14
+ end
15
+ end
16
+
17
+ context 'with configuration' do
18
+ before do
19
+ ActiveRecord::Base.establish_connection(configuration_with_replicas)
20
+ end
21
+
22
+ it 'returns balancer' do
23
+ is_expected.to be_an_instance_of(Multidb::Balancer)
24
+ end
25
+ end
26
+ end
27
+
28
+ describe '.init' do
29
+ subject { described_class.init(config) }
30
+
31
+ let(:config) { configuration_with_replicas }
32
+
33
+ it 'initializes @balancer' do
34
+ expect { subject }.to change {
35
+ described_class.instance_variable_get(:@balancer)
36
+ }.from(nil).to an_instance_of(Multidb::Balancer)
37
+ end
38
+
39
+ it 'initializes the balancer with a configuration object' do
40
+ allow(Multidb::Configuration).to receive(:new)
41
+
42
+ subject
43
+
44
+ expect(Multidb::Configuration).to have_received(:new).with(config.except('multidb'), config['multidb'])
45
+ end
46
+ end
47
+
48
+ describe '.reset!' do
49
+ subject { described_class.reset! }
50
+
51
+ before do
52
+ described_class.instance_variable_set(:@balancer, balancer)
53
+ end
54
+
55
+ it 'clears @balancer' do
56
+ expect { subject }.to change {
57
+ described_class.instance_variable_get(:@balancer)
58
+ }.from(balancer).to(nil)
59
+ end
60
+
61
+ it 'clears the multidb thread local' do
62
+ Thread.current[:multidb] = { some: :value }
63
+
64
+ expect { subject }.to change { Thread.current[:multidb] }.to nil
65
+ end
66
+ end
67
+
68
+ describe 'balancer delegates' do
69
+ before do
70
+ described_class.instance_variable_set(:@balancer, balancer)
71
+ end
72
+
73
+ it 'delegates use to the balancer' do
74
+ described_class.use(:name)
75
+
76
+ expect(balancer).to have_received(:use).with(:name)
77
+ end
78
+
79
+ it 'delegates get to the balancer' do
80
+ described_class.get(:name)
81
+
82
+ expect(balancer).to have_received(:get).with(:name)
83
+ end
84
+
85
+ it 'delegates disconnect! to the balancer' do
86
+ described_class.disconnect!
87
+
88
+ expect(balancer).to have_received(:disconnect!)
89
+ end
90
+ end
91
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+
3
6
  ENV['RACK_ENV'] ||= 'test'
4
7
 
5
8
  require 'rspec'
@@ -10,16 +13,38 @@ require 'fileutils'
10
13
  $LOAD_PATH.unshift(File.expand_path('lib', __dir__))
11
14
  require 'multidb'
12
15
 
13
- require_relative 'helpers'
16
+ Dir[File.join(__dir__, 'support', '**', '*.rb')].sort.each { |f| require f }
14
17
 
15
18
  RSpec.configure do |config|
16
- config.include Helpers
17
- config.expect_with(:rspec) { |c| c.syntax = :should }
18
- config.before :each do
19
+ config.disable_monkey_patching!
20
+ config.order = :random
21
+ Kernel.srand config.seed
22
+
23
+ config.filter_run :focus
24
+ config.run_all_when_everything_filtered = true
25
+
26
+ config.filter_run_excluding rails: lambda { |v|
27
+ rails_version = Gem::Version.new(ActiveRecord::VERSION::STRING)
28
+ test = Gem::Requirement.new(v)
29
+ !test.satisfied_by?(rails_version)
30
+ }
31
+
32
+ config.expect_with :rspec do |expectations|
33
+ expectations.syntax = :expect
34
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
35
+ end
36
+
37
+ config.mock_with :rspec do |mocks|
38
+ mocks.verify_partial_doubles = true
39
+ end
40
+
41
+ config.before do
19
42
  ActiveRecord::Base.clear_all_connections!
20
43
  Multidb.reset!
21
44
  end
22
- config.after :each do
45
+
46
+ config.after do
47
+ Multidb.reset!
23
48
  Dir.glob(File.expand_path('test*.sqlite', __dir__)).each do |f|
24
49
  FileUtils.rm(f)
25
50
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec::Matchers.define :have_database do |expected|
4
+ match do |conn|
5
+ list = conn.execute('pragma database_list')
6
+ @result = File.basename(list.first&.[]('file'))
7
+ @result == expected
8
+ end
9
+ description do
10
+ "be connected to #{expected}"
11
+ end
12
+ failure_message do |actual|
13
+ "expected that #{actual} would be connected to #{expected}, found #{@result}"
14
+ end
15
+ end
@@ -16,8 +16,11 @@ module Helpers
16
16
  - database: spec/test-replica3-1.sqlite
17
17
  - database: spec/test-replica3-2.sqlite
18
18
  replica_alias:
19
- database: spec/test-replica2.sqlite
20
19
  alias: replica2
21
20
  YAML
22
21
  end
23
22
  end
23
+
24
+ RSpec.configure do |config|
25
+ config.include Helpers
26
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar-multidb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Staubo
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-07-20 00:00:00.000000000 Z
12
+ date: 2022-05-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -20,7 +20,7 @@ dependencies:
20
20
  version: '5.1'
21
21
  - - "<"
22
22
  - !ruby/object:Gem::Version
23
- version: '6.0'
23
+ version: '7.1'
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -30,7 +30,7 @@ dependencies:
30
30
  version: '5.1'
31
31
  - - "<"
32
32
  - !ruby/object:Gem::Version
33
- version: '6.0'
33
+ version: '7.1'
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: activesupport
36
36
  requirement: !ruby/object:Gem::Requirement
@@ -40,7 +40,7 @@ dependencies:
40
40
  version: '5.1'
41
41
  - - "<"
42
42
  - !ruby/object:Gem::Version
43
- version: '6.0'
43
+ version: '7.1'
44
44
  type: :runtime
45
45
  prerelease: false
46
46
  version_requirements: !ruby/object:Gem::Requirement
@@ -50,21 +50,21 @@ dependencies:
50
50
  version: '5.1'
51
51
  - - "<"
52
52
  - !ruby/object:Gem::Version
53
- version: '6.0'
53
+ version: '7.1'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: rake
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '12.0'
60
+ version: '13.0'
61
61
  type: :development
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '12.0'
67
+ version: '13.0'
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: rspec
70
70
  requirement: !ruby/object:Gem::Requirement
@@ -85,14 +85,56 @@ dependencies:
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: 0.88.0
88
+ version: 1.28.0
89
89
  type: :development
90
90
  prerelease: false
91
91
  version_requirements: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: 0.88.0
95
+ version: 1.28.0
96
+ - !ruby/object:Gem::Dependency
97
+ name: rubocop-rspec
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 2.10.0
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: 2.10.0
110
+ - !ruby/object:Gem::Dependency
111
+ name: simplecov
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: 0.21.2
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: 0.21.2
124
+ - !ruby/object:Gem::Dependency
125
+ name: simplecov-lcov
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 0.8.0
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: 0.8.0
96
138
  - !ruby/object:Gem::Dependency
97
139
  name: sqlite3
98
140
  requirement: !ruby/object:Gem::Requirement
@@ -116,17 +158,21 @@ executables: []
116
158
  extensions: []
117
159
  extra_rdoc_files: []
118
160
  files:
161
+ - ".github/workflows/prs.yml"
119
162
  - ".gitignore"
120
163
  - ".rubocop.yml"
121
- - ".travis.yml"
164
+ - ".simplecov"
122
165
  - CHANGELOG.md
123
166
  - Gemfile
124
167
  - LICENSE
125
168
  - README.markdown
126
169
  - Rakefile
127
170
  - ar-multidb.gemspec
128
- - gemfiles/activerecord51.gemfile
129
- - gemfiles/activerecord52.gemfile
171
+ - gemfiles/activerecord-5.1.gemfile
172
+ - gemfiles/activerecord-5.2.gemfile
173
+ - gemfiles/activerecord-6.0.gemfile
174
+ - gemfiles/activerecord-6.1.gemfile
175
+ - gemfiles/activerecord-7.0.gemfile
130
176
  - lib/ar-multidb.rb
131
177
  - lib/multidb.rb
132
178
  - lib/multidb/balancer.rb
@@ -135,12 +181,20 @@ files:
135
181
  - lib/multidb/log_subscriber.rb
136
182
  - lib/multidb/model_extensions.rb
137
183
  - lib/multidb/version.rb
138
- - spec/balancer_spec.rb
139
- - spec/helpers.rb
184
+ - spec/lib/multidb/balancer_spec.rb
185
+ - spec/lib/multidb/candidate_spec.rb
186
+ - spec/lib/multidb/configuration_spec.rb
187
+ - spec/lib/multidb/log_subscriber_extension_spec.rb
188
+ - spec/lib/multidb/model_extensions_spec.rb
189
+ - spec/lib/multidb_spec.rb
140
190
  - spec/spec_helper.rb
191
+ - spec/support/have_database_matcher.rb
192
+ - spec/support/helpers.rb
141
193
  homepage: ''
142
- licenses: []
143
- metadata: {}
194
+ licenses:
195
+ - MIT
196
+ metadata:
197
+ rubygems_mfa_required: 'true'
144
198
  post_install_message:
145
199
  rdoc_options: []
146
200
  require_paths:
@@ -149,19 +203,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
149
203
  requirements:
150
204
  - - ">="
151
205
  - !ruby/object:Gem::Version
152
- version: 2.4.0
206
+ version: 2.5.0
153
207
  required_rubygems_version: !ruby/object:Gem::Requirement
154
208
  requirements:
155
209
  - - ">="
156
210
  - !ruby/object:Gem::Version
157
211
  version: '0'
158
212
  requirements: []
159
- rubygems_version: 3.0.6
213
+ rubygems_version: 3.1.6
160
214
  signing_key:
161
215
  specification_version: 4
162
216
  summary: Multidb is an ActiveRecord extension for switching between multiple database
163
217
  connections, such as primary/replica setups.
164
218
  test_files:
165
- - spec/balancer_spec.rb
166
- - spec/helpers.rb
219
+ - spec/lib/multidb/balancer_spec.rb
220
+ - spec/lib/multidb/candidate_spec.rb
221
+ - spec/lib/multidb/configuration_spec.rb
222
+ - spec/lib/multidb/log_subscriber_extension_spec.rb
223
+ - spec/lib/multidb/model_extensions_spec.rb
224
+ - spec/lib/multidb_spec.rb
167
225
  - spec/spec_helper.rb
226
+ - spec/support/have_database_matcher.rb
227
+ - spec/support/helpers.rb
data/.travis.yml DELETED
@@ -1,15 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- cache: bundler
4
-
5
- script:
6
- - bundle exec rubocop
7
- - bundle exec rspec
8
-
9
- matrix:
10
- fast_finish: true
11
- include:
12
- - rvm: 2.5
13
- gemfile: gemfiles/activerecord51.gemfile
14
- - rvm: 2.5
15
- gemfile: gemfiles/activerecord52.gemfile
@@ -1,159 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'spec_helper'
4
-
5
- describe 'Multidb.balancer' do
6
- context 'with no configuration' do
7
- it 'raises exception' do
8
- -> { Multidb.balancer }.should raise_error(Multidb::NotInitializedError)
9
- end
10
- end
11
-
12
- context 'with configuration' do
13
- before do
14
- ActiveRecord::Base.establish_connection(configuration_with_replicas)
15
- end
16
-
17
- it 'returns balancer' do
18
- Multidb.balancer.should_not eq nil
19
- end
20
-
21
- it 'returns main connection by default' do
22
- conn = ActiveRecord::Base.connection
23
-
24
- list = conn.execute('pragma database_list')
25
- list.length.should eq 1
26
- File.basename(list[0]['file']).should eq 'test.sqlite'
27
-
28
- Multidb.balancer.current_connection.should eq conn
29
- end
30
-
31
- it 'returns default connection name for default connection' do
32
- ActiveRecord::Base.connection
33
-
34
- Multidb.balancer.current_connection_name.should eq :default
35
- end
36
-
37
- context 'with additional configurations' do
38
- before do
39
- additional_configuration = { replica4: { database: 'spec/test-replica4.sqlite' } }
40
- Multidb.balancer.append(additional_configuration)
41
- end
42
-
43
- it 'makes the new database available' do
44
- Multidb.use(:replica4) do
45
- conn = ActiveRecord::Base.connection
46
- conn.should eq Multidb.balancer.current_connection
47
- list = conn.execute('pragma database_list')
48
- list.length.should eq 1
49
- File.basename(list[0]['file']).should eq 'test-replica4.sqlite'
50
- end
51
- end
52
-
53
- it 'returns the connection name' do
54
- Multidb.use(:replica4) do
55
- Multidb.balancer.current_connection_name.should eq :replica4
56
- end
57
- end
58
- end
59
- end
60
-
61
- describe '#use' do
62
- context 'with configuration' do
63
- before do
64
- ActiveRecord::Base.establish_connection(configuration_with_replicas)
65
- end
66
-
67
- context 'undefined connection' do
68
- it 'raises exception' do
69
- lambda {
70
- Multidb.use(:something) do
71
- end
72
- }.should raise_error(ArgumentError)
73
- end
74
- end
75
-
76
- it 'returns default connection on :default' do
77
- ActiveRecord::Base.connection
78
- Multidb.use(:default) do
79
- conn2 = ActiveRecord::Base.connection
80
- conn2.should eq Multidb.balancer.current_connection
81
-
82
- list = conn2.execute('pragma database_list')
83
- list.length.should eq 1
84
- File.basename(list[0]['file']).should eq 'test.sqlite'
85
- end
86
- end
87
-
88
- it 'returns replica connection' do
89
- Multidb.use(:replica1) do
90
- conn = ActiveRecord::Base.connection
91
- conn.should eq Multidb.balancer.current_connection
92
- list = conn.execute('pragma database_list')
93
- list.length.should eq 1
94
- File.basename(list[0]['file']).should eq 'test-replica1.sqlite'
95
- end
96
- end
97
-
98
- it 'returns results instead of relation' do
99
- class FooBar < ActiveRecord::Base; end
100
- res = Multidb.use(:replica1) do
101
- ActiveRecord::Migration.verbose = false
102
- ActiveRecord::Schema.define(version: 1) { create_table :foo_bars }
103
- FooBar.where(id: 42)
104
- end
105
- res.should eq []
106
- end
107
-
108
- it 'returns supports nested replica connection' do
109
- Multidb.use(:replica1) do
110
- Multidb.use(:replica2) do
111
- conn = ActiveRecord::Base.connection
112
- conn.should eq Multidb.balancer.current_connection
113
- list = conn.execute('pragma database_list')
114
- list.length.should eq 1
115
- File.basename(list[0]['file']).should eq 'test-replica2.sqlite'
116
- end
117
- end
118
- end
119
-
120
- it 'returns preserves state when nesting' do
121
- Multidb.use(:replica1) do
122
- Multidb.use(:replica2) do
123
- conn = ActiveRecord::Base.connection
124
- conn.should eq Multidb.balancer.current_connection
125
- list = conn.execute('pragma database_list')
126
- list.length.should eq 1
127
- File.basename(list[0]['file']).should eq 'test-replica2.sqlite'
128
- end
129
-
130
- conn = ActiveRecord::Base.connection
131
- conn.should eq Multidb.balancer.current_connection
132
- list = conn.execute('pragma database_list')
133
- list.length.should eq 1
134
- File.basename(list[0]['file']).should eq 'test-replica1.sqlite'
135
- end
136
- end
137
-
138
- it 'returns the parent connection for aliases' do
139
- Multidb.use(:replica1).should_not eq Multidb.use(:replica_alias)
140
- Multidb.use(:replica2).should eq Multidb.use(:replica_alias)
141
- end
142
-
143
- it 'returns random candidate' do
144
- names = []
145
- 100.times do
146
- Multidb.use(:replica3) do
147
- list = ActiveRecord::Base.connection.execute('pragma database_list')
148
- list.length.should eq 1
149
- names.push(File.basename(list[0]['file']))
150
- end
151
- end
152
- names.sort.uniq.should eq [
153
- 'test-replica3-1.sqlite',
154
- 'test-replica3-2.sqlite'
155
- ]
156
- end
157
- end
158
- end
159
- end