ar-multidb 0.5.1 → 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.5.1
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: 2021-10-18 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.1'
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.1'
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.1'
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.1'
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: 1.12.1
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: 1.12.1
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,18 +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
130
- - gemfiles/activerecord60.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
131
176
  - lib/ar-multidb.rb
132
177
  - lib/multidb.rb
133
178
  - lib/multidb/balancer.rb
@@ -136,13 +181,20 @@ files:
136
181
  - lib/multidb/log_subscriber.rb
137
182
  - lib/multidb/model_extensions.rb
138
183
  - lib/multidb/version.rb
139
- - spec/balancer_spec.rb
140
- - 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
141
190
  - spec/spec_helper.rb
191
+ - spec/support/have_database_matcher.rb
192
+ - spec/support/helpers.rb
142
193
  homepage: ''
143
194
  licenses:
144
195
  - MIT
145
- metadata: {}
196
+ metadata:
197
+ rubygems_mfa_required: 'true'
146
198
  post_install_message:
147
199
  rdoc_options: []
148
200
  require_paths:
@@ -151,7 +203,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
151
203
  requirements:
152
204
  - - ">="
153
205
  - !ruby/object:Gem::Version
154
- version: 2.4.0
206
+ version: 2.5.0
155
207
  required_rubygems_version: !ruby/object:Gem::Requirement
156
208
  requirements:
157
209
  - - ">="
@@ -164,6 +216,12 @@ specification_version: 4
164
216
  summary: Multidb is an ActiveRecord extension for switching between multiple database
165
217
  connections, such as primary/replica setups.
166
218
  test_files:
167
- - spec/balancer_spec.rb
168
- - 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
169
225
  - spec/spec_helper.rb
226
+ - spec/support/have_database_matcher.rb
227
+ - spec/support/helpers.rb
data/.travis.yml DELETED
@@ -1,17 +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
16
- - rvm: 2.5
17
- gemfile: gemfiles/activerecord60.gemfile
@@ -1,161 +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
- foobar_class = Class.new(ActiveRecord::Base) do
100
- self.table_name = 'foo_bars'
101
- end
102
- res = Multidb.use(:replica1) do
103
- ActiveRecord::Migration.verbose = false
104
- ActiveRecord::Schema.define(version: 1) { create_table :foo_bars }
105
- foobar_class.where(id: 42)
106
- end
107
- res.should eq []
108
- end
109
-
110
- it 'returns supports nested replica connection' do
111
- Multidb.use(:replica1) do
112
- Multidb.use(:replica2) do
113
- conn = ActiveRecord::Base.connection
114
- conn.should eq Multidb.balancer.current_connection
115
- list = conn.execute('pragma database_list')
116
- list.length.should eq 1
117
- File.basename(list[0]['file']).should eq 'test-replica2.sqlite'
118
- end
119
- end
120
- end
121
-
122
- it 'returns preserves state when nesting' do
123
- Multidb.use(:replica1) do
124
- Multidb.use(:replica2) do
125
- conn = ActiveRecord::Base.connection
126
- conn.should eq Multidb.balancer.current_connection
127
- list = conn.execute('pragma database_list')
128
- list.length.should eq 1
129
- File.basename(list[0]['file']).should eq 'test-replica2.sqlite'
130
- end
131
-
132
- conn = ActiveRecord::Base.connection
133
- conn.should eq Multidb.balancer.current_connection
134
- list = conn.execute('pragma database_list')
135
- list.length.should eq 1
136
- File.basename(list[0]['file']).should eq 'test-replica1.sqlite'
137
- end
138
- end
139
-
140
- it 'returns the parent connection for aliases' do
141
- Multidb.use(:replica1).should_not eq Multidb.use(:replica_alias)
142
- Multidb.use(:replica2).should eq Multidb.use(:replica_alias)
143
- end
144
-
145
- it 'returns random candidate' do
146
- names = []
147
- 100.times do
148
- Multidb.use(:replica3) do
149
- list = ActiveRecord::Base.connection.execute('pragma database_list')
150
- list.length.should eq 1
151
- names.push(File.basename(list[0]['file']))
152
- end
153
- end
154
- names.sort.uniq.should eq [
155
- 'test-replica3-1.sqlite',
156
- 'test-replica3-2.sqlite'
157
- ]
158
- end
159
- end
160
- end
161
- end