ar-multidb 0.4.0 → 0.5.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/.gitignore +3 -0
- data/.rubocop.yml +64 -0
- data/.travis.yml +9 -2
- data/CHANGELOG.md +26 -0
- data/Gemfile +4 -2
- data/LICENSE +1 -1
- data/README.markdown +35 -18
- data/Rakefile +10 -9
- data/ar-multidb.gemspec +20 -17
- data/gemfiles/activerecord51.gemfile +2 -0
- data/gemfiles/activerecord52.gemfile +2 -0
- data/gemfiles/activerecord60.gemfile +7 -0
- data/lib/ar-multidb.rb +2 -0
- data/lib/multidb/balancer.rb +28 -22
- data/lib/multidb/candidate.rb +6 -4
- data/lib/multidb/configuration.rb +7 -10
- data/lib/multidb/log_subscriber.rb +6 -4
- data/lib/multidb/model_extensions.rb +2 -0
- data/lib/multidb/version.rb +3 -1
- data/lib/multidb.rb +2 -0
- data/spec/balancer_spec.rb +38 -31
- data/spec/helpers.rb +21 -18
- data/spec/spec_helper.rb +5 -3
- metadata +54 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffcc496d5d9335e9f71ad121e3ae6eaa4be56a0fc0d28b95b8ec9316b52f6d99
|
4
|
+
data.tar.gz: ce582565fa33aacb84c073f870034a2fb04d6a629f0c311d0d95d8548a31e817
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b023104b3d3f4a50c5db4aa1ffb0a68bcef8af7eca53be1e2c05e7d9eb65213cf8cb25f82cec3dbb4ffe11844fd20da09642f32912580906b929a6d505e2f3c
|
7
|
+
data.tar.gz: 75a697a0f62a8c7219a721d5a0b2390d94521f5c7b48676c17ff8bee958632c8d1f3abf96e2950b69c4a489cb8348136a853f6f2f02522f8b358f6a3aaacdec8
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.4
|
3
|
+
SuggestExtensions: false
|
4
|
+
NewCops: disable
|
5
|
+
Exclude:
|
6
|
+
- '**/vendor/**/*'
|
7
|
+
|
8
|
+
Layout/EmptyLinesAroundAttributeAccessor:
|
9
|
+
Enabled: true
|
10
|
+
Layout/SpaceAroundMethodCallOperator:
|
11
|
+
Enabled: true
|
12
|
+
Layout/LineLength:
|
13
|
+
Exclude:
|
14
|
+
- 'ar-multidb.gemspec'
|
15
|
+
Lint/DeprecatedOpenSSLConstant:
|
16
|
+
Enabled: true
|
17
|
+
Lint/DuplicateElsifCondition:
|
18
|
+
Enabled: true
|
19
|
+
Lint/MixedRegexpCaptureTypes:
|
20
|
+
Enabled: true
|
21
|
+
Lint/RaiseException:
|
22
|
+
Enabled: true
|
23
|
+
Lint/StructNewOverride:
|
24
|
+
Enabled: true
|
25
|
+
Naming/FileName:
|
26
|
+
Exclude:
|
27
|
+
- 'lib/ar-multidb.rb'
|
28
|
+
Metrics:
|
29
|
+
Enabled: false
|
30
|
+
Style/AccessorGrouping:
|
31
|
+
Enabled: true
|
32
|
+
Style/ArrayCoercion:
|
33
|
+
Enabled: true
|
34
|
+
Style/BisectedAttrAccessor:
|
35
|
+
Enabled: true
|
36
|
+
Style/CaseLikeIf:
|
37
|
+
Enabled: true
|
38
|
+
Style/Documentation:
|
39
|
+
Enabled: false
|
40
|
+
Style/ExponentialNotation:
|
41
|
+
Enabled: true
|
42
|
+
Style/HashAsLastArrayItem:
|
43
|
+
Enabled: true
|
44
|
+
Style/HashEachMethods:
|
45
|
+
Enabled: true
|
46
|
+
Style/HashLikeCase:
|
47
|
+
Enabled: true
|
48
|
+
Style/HashTransformKeys:
|
49
|
+
Enabled: true
|
50
|
+
Style/HashTransformValues:
|
51
|
+
Enabled: true
|
52
|
+
Style/RedundantAssignment:
|
53
|
+
Enabled: true
|
54
|
+
Style/RedundantFetchBlock:
|
55
|
+
Enabled: true
|
56
|
+
Style/RedundantFileExtensionInRequire:
|
57
|
+
Enabled: true
|
58
|
+
Style/RedundantRegexpCharacterClass:
|
59
|
+
Enabled: true
|
60
|
+
Style/RedundantRegexpEscape:
|
61
|
+
Enabled: true
|
62
|
+
Style/SlicingWithRange:
|
63
|
+
Enabled: true
|
64
|
+
|
data/.travis.yml
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
|
+
cache: bundler
|
4
|
+
|
5
|
+
script:
|
6
|
+
- bundle exec rubocop
|
7
|
+
- bundle exec rspec
|
3
8
|
|
4
9
|
matrix:
|
5
10
|
fast_finish: true
|
6
11
|
include:
|
7
|
-
- rvm: 2.5
|
12
|
+
- rvm: 2.5
|
8
13
|
gemfile: gemfiles/activerecord51.gemfile
|
9
|
-
- rvm: 2.5
|
14
|
+
- rvm: 2.5
|
10
15
|
gemfile: gemfiles/activerecord52.gemfile
|
16
|
+
- rvm: 2.5
|
17
|
+
gemfile: gemfiles/activerecord60.gemfile
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
5
|
+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html)
|
6
|
+
|
7
|
+
## [0.5.1]
|
8
|
+
### Fixed
|
9
|
+
- corrected licenses
|
10
|
+
### Changed
|
11
|
+
- updated to newer rubocop
|
12
|
+
|
13
|
+
## [0.5.0]
|
14
|
+
### Changed
|
15
|
+
- added rails 6 support
|
16
|
+
|
17
|
+
## [0.4.2]
|
18
|
+
### Changed
|
19
|
+
- adjust rails restriction to exclude untested rails 6
|
20
|
+
- adjust minimum ruby version to 2.4
|
21
|
+
- add rubocop
|
22
|
+
|
23
|
+
## [0.4.1]
|
24
|
+
### Added
|
25
|
+
- Added support for database aliases ( PR #26 )
|
26
|
+
|
data/Gemfile
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'http://rubygems.org'
|
2
4
|
|
3
5
|
# Specify your gem's dependencies in ar-multidb.gemspec
|
4
6
|
gemspec
|
5
7
|
|
6
|
-
local_gemfile =
|
8
|
+
local_gemfile = 'Gemfile.local'
|
7
9
|
|
8
10
|
if File.exist?(local_gemfile)
|
9
11
|
eval(File.read(local_gemfile)) # rubocop:disable Security/Eval
|
data/LICENSE
CHANGED
data/README.markdown
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
# Multidb
|
4
4
|
|
5
|
-
A simple, no-nonsense ActiveRecord extension which allows the application to switch between multiple database connections, such as in a
|
5
|
+
A simple, no-nonsense ActiveRecord extension which allows the application to switch between multiple database connections, such as in a primary/replica environment. For example:
|
6
6
|
|
7
|
-
Multidb.use(:
|
7
|
+
Multidb.use(:replica) do
|
8
8
|
@posts = Post.all
|
9
9
|
end
|
10
10
|
|
@@ -14,7 +14,7 @@ Randomized balancing of multiple connections within a group is supported. In the
|
|
14
14
|
|
15
15
|
## Requirements
|
16
16
|
|
17
|
-
* Ruby 2.
|
17
|
+
* Ruby 2.4 or later.
|
18
18
|
* ActiveRecord 5.1 or later.
|
19
19
|
|
20
20
|
## Older releases
|
@@ -32,10 +32,10 @@ Compared to other, more full-featured extensions such as Octopus and Seamless Da
|
|
32
32
|
|
33
33
|
**Orthogonal**. Unlike Octopus, for example, connections follow context:
|
34
34
|
|
35
|
-
Multidb.use(:
|
35
|
+
Multidb.use(:primary) do
|
36
36
|
@post = Post.find(1)
|
37
|
-
Multidb.use(:
|
38
|
-
@post.authors # This will use the
|
37
|
+
Multidb.use(:replica) do
|
38
|
+
@post.authors # This will use the replica
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -60,8 +60,8 @@ All that is needed is to set up your `database.yml` file:
|
|
60
60
|
host: db1
|
61
61
|
multidb:
|
62
62
|
databases:
|
63
|
-
|
64
|
-
host: db-
|
63
|
+
replica:
|
64
|
+
host: db-replica
|
65
65
|
|
66
66
|
Each database entry may be a hash or an array. So this also works:
|
67
67
|
|
@@ -73,24 +73,41 @@ Each database entry may be a hash or an array. So this also works:
|
|
73
73
|
host: db1
|
74
74
|
multidb:
|
75
75
|
databases:
|
76
|
-
|
77
|
-
- host: db-
|
78
|
-
- host: db-
|
76
|
+
replica:
|
77
|
+
- host: db-replica1
|
78
|
+
- host: db-replica2
|
79
79
|
|
80
80
|
If multiple elements are specified, Multidb will use the list to pick a random candidate connection.
|
81
81
|
|
82
82
|
The database hashes follow the same format as the top-level adapter configuration. In other words, each database connection may override the adapter, database name, username and so on.
|
83
83
|
|
84
|
+
You may also add an "alias" record to the configuration to support more than one name for a given database configuration.
|
85
|
+
|
86
|
+
production:
|
87
|
+
adapter: postgresql
|
88
|
+
database: myapp_production
|
89
|
+
username: ohoh
|
90
|
+
password: mymy
|
91
|
+
host: db1
|
92
|
+
multidb:
|
93
|
+
databases:
|
94
|
+
main_db:
|
95
|
+
host: db1-a
|
96
|
+
secondary_db:
|
97
|
+
alias: main_db
|
98
|
+
|
99
|
+
With the above, `Multidb.use(:main_db)` and `Multidb.use(:secondary_db)` will work identically. This can be useful to support naming scheme migrations transparently: once your application is updated to use `secondary_db` where necessary, you can swap out the configuration.
|
100
|
+
|
84
101
|
To use the connection, modify your code by wrapping database access logic in blocks:
|
85
102
|
|
86
|
-
Multidb.use(:
|
103
|
+
Multidb.use(:replica) do
|
87
104
|
@posts = Post.all
|
88
105
|
end
|
89
106
|
|
90
107
|
To wrap entire controller requests, for example:
|
91
108
|
|
92
109
|
class PostsController < ApplicationController
|
93
|
-
around_filter :
|
110
|
+
around_filter :run_using_replica, only: [:index]
|
94
111
|
|
95
112
|
def index
|
96
113
|
@posts = Post.all
|
@@ -100,22 +117,22 @@ To wrap entire controller requests, for example:
|
|
100
117
|
# Won't be wrapped
|
101
118
|
end
|
102
119
|
|
103
|
-
def
|
104
|
-
Multidb.use(:
|
120
|
+
def run_using_replica(&block)
|
121
|
+
Multidb.use(:replica, &block)
|
105
122
|
end
|
106
123
|
end
|
107
124
|
|
108
125
|
You can also set the current connection for the remainder of the thread's execution:
|
109
126
|
|
110
|
-
Multidb.use(:
|
127
|
+
Multidb.use(:replica)
|
111
128
|
# Do work
|
112
|
-
Multidb.use(:
|
129
|
+
Multidb.use(:primary)
|
113
130
|
|
114
131
|
Note that the symbol `:default` will (unless you override it) refer to the default top-level ActiveRecord configuration.
|
115
132
|
|
116
133
|
## Development mode
|
117
134
|
|
118
|
-
In development you will typically want `Multidb.use(:
|
135
|
+
In development you will typically want `Multidb.use(:replica)` to still work, but you probably don't want to run multiple databases on your development box. To make `use` silently fall back to using the default connection, Multidb can run in fallback mode.
|
119
136
|
|
120
137
|
If you are using Rails, this will be automatically enabled in `development` and `test` environments. Otherwise, simply set `fallback: true` in `database.yml`:
|
121
138
|
|
data/Rakefile
CHANGED
@@ -1,26 +1,27 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
2
4
|
require 'rspec/core/rake_task'
|
3
5
|
|
4
6
|
RSpec::Core::RakeTask.new
|
5
7
|
|
6
|
-
task :
|
8
|
+
task default: :spec
|
7
9
|
|
8
10
|
desc 'Bump version'
|
9
11
|
task :bump do
|
10
|
-
if `git status -uno -s --porcelain | wc -l`.to_i
|
11
|
-
|
12
|
-
end
|
12
|
+
abort 'You have uncommitted changed.' if `git status -uno -s --porcelain | wc -l`.to_i.positive?
|
13
|
+
|
13
14
|
text = File.read('lib/multidb/version.rb')
|
14
15
|
if text =~ /VERSION = '(.*)'/
|
15
|
-
old_version =
|
16
|
+
old_version = Regexp.last_match(1)
|
16
17
|
version_parts = old_version.split('.')
|
17
18
|
version_parts[-1] = version_parts[-1].to_i + 1
|
18
19
|
new_version = version_parts.join('.')
|
19
20
|
text.gsub!(/VERSION = '(.*)'/, "VERSION = '#{new_version}'")
|
20
21
|
File.open('lib/multidb/version.rb', 'w') { |f| f << text }
|
21
|
-
(system(
|
22
|
-
system("git commit -m 'Bump to #{new_version}.'"))
|
22
|
+
(system('git add lib/multidb/version.rb') &&
|
23
|
+
system("git commit -m 'Bump to #{new_version}.'")) || abort('Failed to commit.')
|
23
24
|
else
|
24
|
-
abort
|
25
|
+
abort 'Could not find version number'
|
25
26
|
end
|
26
27
|
end
|
data/ar-multidb.gemspec
CHANGED
@@ -1,26 +1,29 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
4
|
+
require 'multidb/version'
|
4
5
|
|
5
6
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
7
|
+
s.name = 'ar-multidb'
|
7
8
|
s.version = Multidb::VERSION
|
8
|
-
s.authors = [
|
9
|
-
s.email = [
|
10
|
-
s.homepage =
|
11
|
-
s.summary = s.description =
|
12
|
-
|
13
|
-
s.rubyforge_project = "ar-multidb"
|
9
|
+
s.authors = ['Alexander Staubo', 'Edward Rudd']
|
10
|
+
s.email = ['alex@bengler.no', 'urkle@outoforder.cc']
|
11
|
+
s.homepage = ''
|
12
|
+
s.summary = s.description = 'Multidb is an ActiveRecord extension for switching between multiple database connections, such as primary/replica setups.'
|
13
|
+
s.license = 'MIT'
|
14
14
|
|
15
15
|
s.files = `git ls-files`.split("\n")
|
16
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
-
s.require_paths = [
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
|
20
|
+
s.required_ruby_version = '>= 2.4.0'
|
19
21
|
|
20
|
-
s.add_runtime_dependency '
|
21
|
-
s.add_runtime_dependency '
|
22
|
+
s.add_runtime_dependency 'activerecord', '>= 5.1', '< 6.1'
|
23
|
+
s.add_runtime_dependency 'activesupport', '>= 5.1', '< 6.1'
|
22
24
|
|
23
|
-
s.add_development_dependency '
|
24
|
-
s.add_development_dependency '
|
25
|
-
s.add_development_dependency '
|
25
|
+
s.add_development_dependency 'rake', '~> 12.0'
|
26
|
+
s.add_development_dependency 'rspec', '~> 3.8'
|
27
|
+
s.add_development_dependency 'rubocop', '~> 1.12.1'
|
28
|
+
s.add_development_dependency 'sqlite3', '~> 1.3'
|
26
29
|
end
|
data/lib/ar-multidb.rb
CHANGED
data/lib/multidb/balancer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Multidb
|
2
4
|
class Balancer
|
3
5
|
attr_accessor :fallback
|
@@ -6,29 +8,33 @@ module Multidb
|
|
6
8
|
@candidates = {}.with_indifferent_access
|
7
9
|
@default_configuration = configuration
|
8
10
|
|
9
|
-
|
11
|
+
return unless @default_configuration
|
10
12
|
|
11
|
-
|
13
|
+
append(@default_configuration.raw_configuration[:databases] || {})
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
15
|
+
@fallback = if @default_configuration.raw_configuration.include?(:fallback)
|
16
|
+
@default_configuration.raw_configuration[:fallback]
|
17
|
+
elsif defined?(Rails)
|
18
|
+
%w[development test].include?(Rails.env)
|
19
|
+
else
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
@default_candidate = Candidate.new('default', @default_configuration.default_handler)
|
24
|
+
|
25
|
+
@candidates[:default] = [@default_candidate] unless @candidates.include?(:default)
|
25
26
|
end
|
26
27
|
|
27
28
|
def append(databases)
|
28
29
|
databases.each_pair do |name, config|
|
29
30
|
configs = config.is_a?(Array) ? config : [config]
|
30
|
-
configs.each do |
|
31
|
-
|
31
|
+
configs.each do |cfg|
|
32
|
+
if cfg['alias']
|
33
|
+
@candidates[name] = @candidates[cfg['alias']]
|
34
|
+
next
|
35
|
+
end
|
36
|
+
|
37
|
+
candidate = Candidate.new(name, @default_configuration.default_adapter.merge(cfg))
|
32
38
|
@candidates[name] ||= []
|
33
39
|
@candidates[name].push(candidate)
|
34
40
|
end
|
@@ -39,16 +45,18 @@ module Multidb
|
|
39
45
|
@candidates.values.flatten.each(&:disconnect!)
|
40
46
|
end
|
41
47
|
|
42
|
-
def get(name, &
|
48
|
+
def get(name, &_block)
|
43
49
|
candidates = @candidates[name]
|
44
50
|
candidates ||= @fallback ? @candidates[:default] : []
|
51
|
+
|
45
52
|
raise ArgumentError, "No such database connection '#{name}'" if candidates.empty?
|
46
|
-
|
47
|
-
|
53
|
+
|
54
|
+
candidate = candidates.respond_to?(:sample) ? candidates.sample : candidates[rand(candidates.length)]
|
55
|
+
|
48
56
|
block_given? ? yield(candidate) : candidate
|
49
57
|
end
|
50
58
|
|
51
|
-
def use(name, &
|
59
|
+
def use(name, &_block)
|
52
60
|
result = nil
|
53
61
|
get(name) do |candidate|
|
54
62
|
if block_given?
|
@@ -110,7 +118,5 @@ module Multidb
|
|
110
118
|
Multidb.balancer.disconnect!
|
111
119
|
end
|
112
120
|
end
|
113
|
-
|
114
121
|
end
|
115
|
-
|
116
122
|
end
|
data/lib/multidb/candidate.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Multidb
|
2
4
|
class Candidate
|
3
5
|
def initialize(name, target)
|
4
6
|
@name = name
|
5
7
|
|
6
|
-
|
8
|
+
case target
|
9
|
+
when Hash
|
7
10
|
@connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
|
8
11
|
@connection_handler.establish_connection(target.merge(name: 'primary'))
|
9
|
-
|
12
|
+
when ActiveRecord::ConnectionAdapters::ConnectionHandler
|
10
13
|
@connection_handler = target
|
11
14
|
else
|
12
15
|
raise ArgumentError, 'Connection handler not passed to target'
|
13
16
|
end
|
14
|
-
|
15
17
|
end
|
16
18
|
|
17
19
|
def connection(&block)
|
@@ -28,4 +30,4 @@ module Multidb
|
|
28
30
|
|
29
31
|
attr_reader :name
|
30
32
|
end
|
31
|
-
end
|
33
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Multidb
|
2
4
|
class << self
|
3
5
|
delegate :use, :get, :disconnect!, to: :balancer
|
@@ -5,17 +7,14 @@ module Multidb
|
|
5
7
|
|
6
8
|
def self.init(config)
|
7
9
|
activerecord_config = config.dup.with_indifferent_access
|
8
|
-
default_adapter
|
10
|
+
default_adapter = activerecord_config
|
11
|
+
configuration_hash = activerecord_config.delete(:multidb)
|
9
12
|
|
10
13
|
@balancer = Balancer.new(Configuration.new(default_adapter, configuration_hash || {}))
|
11
14
|
end
|
12
15
|
|
13
16
|
def self.balancer
|
14
|
-
|
15
|
-
@balancer
|
16
|
-
else
|
17
|
-
raise NotInitializedError, "Balancer not initialized. You need to run Multidb.init first"
|
18
|
-
end
|
17
|
+
@balancer || raise(NotInitializedError, 'Balancer not initialized. You need to run Multidb.init first')
|
19
18
|
end
|
20
19
|
|
21
20
|
def self.reset!
|
@@ -31,8 +30,6 @@ module Multidb
|
|
31
30
|
@raw_configuration = configuration_hash
|
32
31
|
end
|
33
32
|
|
34
|
-
attr_reader :default_handler
|
35
|
-
attr_reader :default_adapter
|
36
|
-
attr_reader :raw_configuration
|
33
|
+
attr_reader :default_handler, :default_adapter, :raw_configuration
|
37
34
|
end
|
38
|
-
end
|
35
|
+
end
|
@@ -1,14 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Multidb
|
2
4
|
module LogSubscriberExtension
|
3
5
|
def sql(event)
|
4
|
-
|
5
|
-
|
6
|
-
end
|
6
|
+
name = Multidb.balancer.current_connection_name
|
7
|
+
event.payload[:db_name] = name if name
|
7
8
|
super
|
8
9
|
end
|
9
10
|
|
10
11
|
def debug(msg)
|
11
|
-
|
12
|
+
name = Multidb.balancer.current_connection_name
|
13
|
+
if name
|
12
14
|
db = color("[DB: #{name}]", ActiveSupport::LogSubscriber::GREEN, true)
|
13
15
|
super(db + msg)
|
14
16
|
else
|
data/lib/multidb/version.rb
CHANGED
data/lib/multidb.rb
CHANGED
data/spec/balancer_spec.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'spec_helper'
|
2
4
|
|
3
5
|
describe 'Multidb.balancer' do
|
4
|
-
|
5
6
|
context 'with no configuration' do
|
6
7
|
it 'raises exception' do
|
7
8
|
-> { Multidb.balancer }.should raise_error(Multidb::NotInitializedError)
|
@@ -10,7 +11,7 @@ describe 'Multidb.balancer' do
|
|
10
11
|
|
11
12
|
context 'with configuration' do
|
12
13
|
before do
|
13
|
-
ActiveRecord::Base.establish_connection(
|
14
|
+
ActiveRecord::Base.establish_connection(configuration_with_replicas)
|
14
15
|
end
|
15
16
|
|
16
17
|
it 'returns balancer' do
|
@@ -28,30 +29,30 @@ describe 'Multidb.balancer' do
|
|
28
29
|
end
|
29
30
|
|
30
31
|
it 'returns default connection name for default connection' do
|
31
|
-
|
32
|
+
ActiveRecord::Base.connection
|
32
33
|
|
33
34
|
Multidb.balancer.current_connection_name.should eq :default
|
34
35
|
end
|
35
|
-
|
36
|
+
|
36
37
|
context 'with additional configurations' do
|
37
38
|
before do
|
38
|
-
additional_configuration = {
|
39
|
+
additional_configuration = { replica4: { database: 'spec/test-replica4.sqlite' } }
|
39
40
|
Multidb.balancer.append(additional_configuration)
|
40
41
|
end
|
41
42
|
|
42
43
|
it 'makes the new database available' do
|
43
|
-
Multidb.use(:
|
44
|
+
Multidb.use(:replica4) do
|
44
45
|
conn = ActiveRecord::Base.connection
|
45
46
|
conn.should eq Multidb.balancer.current_connection
|
46
47
|
list = conn.execute('pragma database_list')
|
47
48
|
list.length.should eq 1
|
48
|
-
File.basename(list[0]['file']).should eq 'test-
|
49
|
+
File.basename(list[0]['file']).should eq 'test-replica4.sqlite'
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
52
53
|
it 'returns the connection name' do
|
53
|
-
Multidb.use(:
|
54
|
-
Multidb.balancer.current_connection_name.should eq :
|
54
|
+
Multidb.use(:replica4) do
|
55
|
+
Multidb.balancer.current_connection_name.should eq :replica4
|
55
56
|
end
|
56
57
|
end
|
57
58
|
end
|
@@ -60,12 +61,12 @@ describe 'Multidb.balancer' do
|
|
60
61
|
describe '#use' do
|
61
62
|
context 'with configuration' do
|
62
63
|
before do
|
63
|
-
ActiveRecord::Base.establish_connection(
|
64
|
+
ActiveRecord::Base.establish_connection(configuration_with_replicas)
|
64
65
|
end
|
65
66
|
|
66
67
|
context 'undefined connection' do
|
67
68
|
it 'raises exception' do
|
68
|
-
|
69
|
+
lambda {
|
69
70
|
Multidb.use(:something) do
|
70
71
|
end
|
71
72
|
}.should raise_error(ArgumentError)
|
@@ -73,7 +74,7 @@ describe 'Multidb.balancer' do
|
|
73
74
|
end
|
74
75
|
|
75
76
|
it 'returns default connection on :default' do
|
76
|
-
|
77
|
+
ActiveRecord::Base.connection
|
77
78
|
Multidb.use(:default) do
|
78
79
|
conn2 = ActiveRecord::Base.connection
|
79
80
|
conn2.should eq Multidb.balancer.current_connection
|
@@ -84,71 +85,77 @@ describe 'Multidb.balancer' do
|
|
84
85
|
end
|
85
86
|
end
|
86
87
|
|
87
|
-
it 'returns
|
88
|
-
Multidb.use(:
|
88
|
+
it 'returns replica connection' do
|
89
|
+
Multidb.use(:replica1) do
|
89
90
|
conn = ActiveRecord::Base.connection
|
90
91
|
conn.should eq Multidb.balancer.current_connection
|
91
92
|
list = conn.execute('pragma database_list')
|
92
93
|
list.length.should eq 1
|
93
|
-
File.basename(list[0]['file']).should eq 'test-
|
94
|
+
File.basename(list[0]['file']).should eq 'test-replica1.sqlite'
|
94
95
|
end
|
95
96
|
end
|
96
97
|
|
97
98
|
it 'returns results instead of relation' do
|
98
|
-
|
99
|
-
|
99
|
+
foobar_class = Class.new(ActiveRecord::Base) do
|
100
|
+
self.table_name = 'foo_bars'
|
101
|
+
end
|
102
|
+
res = Multidb.use(:replica1) do
|
100
103
|
ActiveRecord::Migration.verbose = false
|
101
104
|
ActiveRecord::Schema.define(version: 1) { create_table :foo_bars }
|
102
|
-
|
105
|
+
foobar_class.where(id: 42)
|
103
106
|
end
|
104
107
|
res.should eq []
|
105
108
|
end
|
106
109
|
|
107
|
-
it 'returns supports nested
|
108
|
-
Multidb.use(:
|
109
|
-
Multidb.use(:
|
110
|
+
it 'returns supports nested replica connection' do
|
111
|
+
Multidb.use(:replica1) do
|
112
|
+
Multidb.use(:replica2) do
|
110
113
|
conn = ActiveRecord::Base.connection
|
111
114
|
conn.should eq Multidb.balancer.current_connection
|
112
115
|
list = conn.execute('pragma database_list')
|
113
116
|
list.length.should eq 1
|
114
|
-
File.basename(list[0]['file']).should eq 'test-
|
117
|
+
File.basename(list[0]['file']).should eq 'test-replica2.sqlite'
|
115
118
|
end
|
116
119
|
end
|
117
120
|
end
|
118
121
|
|
119
122
|
it 'returns preserves state when nesting' do
|
120
|
-
Multidb.use(:
|
121
|
-
Multidb.use(:
|
123
|
+
Multidb.use(:replica1) do
|
124
|
+
Multidb.use(:replica2) do
|
122
125
|
conn = ActiveRecord::Base.connection
|
123
126
|
conn.should eq Multidb.balancer.current_connection
|
124
127
|
list = conn.execute('pragma database_list')
|
125
128
|
list.length.should eq 1
|
126
|
-
File.basename(list[0]['file']).should eq 'test-
|
129
|
+
File.basename(list[0]['file']).should eq 'test-replica2.sqlite'
|
127
130
|
end
|
128
131
|
|
129
132
|
conn = ActiveRecord::Base.connection
|
130
133
|
conn.should eq Multidb.balancer.current_connection
|
131
134
|
list = conn.execute('pragma database_list')
|
132
135
|
list.length.should eq 1
|
133
|
-
File.basename(list[0]['file']).should eq 'test-
|
136
|
+
File.basename(list[0]['file']).should eq 'test-replica1.sqlite'
|
134
137
|
end
|
135
138
|
end
|
136
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
|
+
|
137
145
|
it 'returns random candidate' do
|
138
146
|
names = []
|
139
147
|
100.times do
|
140
|
-
Multidb.use(:
|
148
|
+
Multidb.use(:replica3) do
|
141
149
|
list = ActiveRecord::Base.connection.execute('pragma database_list')
|
142
150
|
list.length.should eq 1
|
143
151
|
names.push(File.basename(list[0]['file']))
|
144
152
|
end
|
145
153
|
end
|
146
154
|
names.sort.uniq.should eq [
|
147
|
-
'test-
|
148
|
-
'test-
|
155
|
+
'test-replica3-1.sqlite',
|
156
|
+
'test-replica3-2.sqlite'
|
149
157
|
]
|
150
158
|
end
|
151
159
|
end
|
152
160
|
end
|
153
|
-
|
154
|
-
end
|
161
|
+
end
|
data/spec/helpers.rb
CHANGED
@@ -1,20 +1,23 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
3
|
+
module Helpers
|
4
|
+
def configuration_with_replicas
|
5
|
+
YAML.safe_load(<<~YAML)
|
6
|
+
adapter: sqlite3
|
7
|
+
database: spec/test.sqlite
|
8
|
+
encoding: utf-8
|
9
|
+
multidb:
|
10
|
+
databases:
|
11
|
+
replica1:
|
12
|
+
database: spec/test-replica1.sqlite
|
13
|
+
replica2:
|
14
|
+
database: spec/test-replica2.sqlite
|
15
|
+
replica3:
|
16
|
+
- database: spec/test-replica3-1.sqlite
|
17
|
+
- database: spec/test-replica3-2.sqlite
|
18
|
+
replica_alias:
|
19
|
+
database: spec/test-replica2.sqlite
|
20
|
+
alias: replica2
|
21
|
+
YAML
|
18
22
|
end
|
19
|
-
|
20
|
-
end
|
23
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
ENV['RACK_ENV'] ||= 'test'
|
2
4
|
|
3
5
|
require 'rspec'
|
4
6
|
require 'yaml'
|
5
7
|
require 'active_record'
|
6
8
|
require 'fileutils'
|
7
9
|
|
8
|
-
$LOAD_PATH.unshift(File.expand_path('
|
10
|
+
$LOAD_PATH.unshift(File.expand_path('lib', __dir__))
|
9
11
|
require 'multidb'
|
10
12
|
|
11
13
|
require_relative 'helpers'
|
@@ -18,7 +20,7 @@ RSpec.configure do |config|
|
|
18
20
|
Multidb.reset!
|
19
21
|
end
|
20
22
|
config.after :each do
|
21
|
-
Dir.glob(File.expand_path('
|
23
|
+
Dir.glob(File.expand_path('test*.sqlite', __dir__)).each do |f|
|
22
24
|
FileUtils.rm(f)
|
23
25
|
end
|
24
26
|
end
|
metadata
CHANGED
@@ -1,25 +1,26 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar-multidb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexander Staubo
|
8
|
-
|
8
|
+
- Edward Rudd
|
9
|
+
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2021-10-18 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
+
name: activerecord
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
18
|
- - ">="
|
18
19
|
- !ruby/object:Gem::Version
|
19
20
|
version: '5.1'
|
20
|
-
- - "
|
21
|
+
- - "<"
|
21
22
|
- !ruby/object:Gem::Version
|
22
|
-
version: '6.
|
23
|
+
version: '6.1'
|
23
24
|
type: :runtime
|
24
25
|
prerelease: false
|
25
26
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -27,19 +28,19 @@ dependencies:
|
|
27
28
|
- - ">="
|
28
29
|
- !ruby/object:Gem::Version
|
29
30
|
version: '5.1'
|
30
|
-
- - "
|
31
|
+
- - "<"
|
31
32
|
- !ruby/object:Gem::Version
|
32
|
-
version: '6.
|
33
|
+
version: '6.1'
|
33
34
|
- !ruby/object:Gem::Dependency
|
34
|
-
name:
|
35
|
+
name: activesupport
|
35
36
|
requirement: !ruby/object:Gem::Requirement
|
36
37
|
requirements:
|
37
38
|
- - ">="
|
38
39
|
- !ruby/object:Gem::Version
|
39
40
|
version: '5.1'
|
40
|
-
- - "
|
41
|
+
- - "<"
|
41
42
|
- !ruby/object:Gem::Version
|
42
|
-
version: '6.
|
43
|
+
version: '6.1'
|
43
44
|
type: :runtime
|
44
45
|
prerelease: false
|
45
46
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -47,61 +48,78 @@ dependencies:
|
|
47
48
|
- - ">="
|
48
49
|
- !ruby/object:Gem::Version
|
49
50
|
version: '5.1'
|
50
|
-
- - "
|
51
|
+
- - "<"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '6.1'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: rake
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '12.0'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
51
66
|
- !ruby/object:Gem::Version
|
52
|
-
version: '
|
67
|
+
version: '12.0'
|
53
68
|
- !ruby/object:Gem::Dependency
|
54
69
|
name: rspec
|
55
70
|
requirement: !ruby/object:Gem::Requirement
|
56
71
|
requirements:
|
57
|
-
- - "
|
72
|
+
- - "~>"
|
58
73
|
- !ruby/object:Gem::Version
|
59
|
-
version: '
|
74
|
+
version: '3.8'
|
60
75
|
type: :development
|
61
76
|
prerelease: false
|
62
77
|
version_requirements: !ruby/object:Gem::Requirement
|
63
78
|
requirements:
|
64
|
-
- - "
|
79
|
+
- - "~>"
|
65
80
|
- !ruby/object:Gem::Version
|
66
|
-
version: '
|
81
|
+
version: '3.8'
|
67
82
|
- !ruby/object:Gem::Dependency
|
68
|
-
name:
|
83
|
+
name: rubocop
|
69
84
|
requirement: !ruby/object:Gem::Requirement
|
70
85
|
requirements:
|
71
|
-
- - "
|
86
|
+
- - "~>"
|
72
87
|
- !ruby/object:Gem::Version
|
73
|
-
version:
|
88
|
+
version: 1.12.1
|
74
89
|
type: :development
|
75
90
|
prerelease: false
|
76
91
|
version_requirements: !ruby/object:Gem::Requirement
|
77
92
|
requirements:
|
78
|
-
- - "
|
93
|
+
- - "~>"
|
79
94
|
- !ruby/object:Gem::Version
|
80
|
-
version:
|
95
|
+
version: 1.12.1
|
81
96
|
- !ruby/object:Gem::Dependency
|
82
|
-
name:
|
97
|
+
name: sqlite3
|
83
98
|
requirement: !ruby/object:Gem::Requirement
|
84
99
|
requirements:
|
85
|
-
- - "
|
100
|
+
- - "~>"
|
86
101
|
- !ruby/object:Gem::Version
|
87
|
-
version: '
|
102
|
+
version: '1.3'
|
88
103
|
type: :development
|
89
104
|
prerelease: false
|
90
105
|
version_requirements: !ruby/object:Gem::Requirement
|
91
106
|
requirements:
|
92
|
-
- - "
|
107
|
+
- - "~>"
|
93
108
|
- !ruby/object:Gem::Version
|
94
|
-
version: '
|
109
|
+
version: '1.3'
|
95
110
|
description: Multidb is an ActiveRecord extension for switching between multiple database
|
96
|
-
connections, such as
|
111
|
+
connections, such as primary/replica setups.
|
97
112
|
email:
|
98
113
|
- alex@bengler.no
|
114
|
+
- urkle@outoforder.cc
|
99
115
|
executables: []
|
100
116
|
extensions: []
|
101
117
|
extra_rdoc_files: []
|
102
118
|
files:
|
103
119
|
- ".gitignore"
|
120
|
+
- ".rubocop.yml"
|
104
121
|
- ".travis.yml"
|
122
|
+
- CHANGELOG.md
|
105
123
|
- Gemfile
|
106
124
|
- LICENSE
|
107
125
|
- README.markdown
|
@@ -109,6 +127,7 @@ files:
|
|
109
127
|
- ar-multidb.gemspec
|
110
128
|
- gemfiles/activerecord51.gemfile
|
111
129
|
- gemfiles/activerecord52.gemfile
|
130
|
+
- gemfiles/activerecord60.gemfile
|
112
131
|
- lib/ar-multidb.rb
|
113
132
|
- lib/multidb.rb
|
114
133
|
- lib/multidb/balancer.rb
|
@@ -121,9 +140,10 @@ files:
|
|
121
140
|
- spec/helpers.rb
|
122
141
|
- spec/spec_helper.rb
|
123
142
|
homepage: ''
|
124
|
-
licenses:
|
143
|
+
licenses:
|
144
|
+
- MIT
|
125
145
|
metadata: {}
|
126
|
-
post_install_message:
|
146
|
+
post_install_message:
|
127
147
|
rdoc_options: []
|
128
148
|
require_paths:
|
129
149
|
- lib
|
@@ -131,19 +151,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
131
151
|
requirements:
|
132
152
|
- - ">="
|
133
153
|
- !ruby/object:Gem::Version
|
134
|
-
version:
|
154
|
+
version: 2.4.0
|
135
155
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
156
|
requirements:
|
137
157
|
- - ">="
|
138
158
|
- !ruby/object:Gem::Version
|
139
159
|
version: '0'
|
140
160
|
requirements: []
|
141
|
-
|
142
|
-
|
143
|
-
signing_key:
|
161
|
+
rubygems_version: 3.1.6
|
162
|
+
signing_key:
|
144
163
|
specification_version: 4
|
145
164
|
summary: Multidb is an ActiveRecord extension for switching between multiple database
|
146
|
-
connections, such as
|
165
|
+
connections, such as primary/replica setups.
|
147
166
|
test_files:
|
148
167
|
- spec/balancer_spec.rb
|
149
168
|
- spec/helpers.rb
|