ar-multidb 0.1.13 → 0.5.0
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 +5 -5
- data/.gitignore +5 -0
- data/.rubocop.yml +62 -0
- data/.travis.yml +17 -3
- data/CHANGELOG.md +20 -0
- data/Gemfile +7 -4
- data/README.markdown +41 -19
- data/Rakefile +10 -9
- data/ar-multidb.gemspec +19 -16
- data/gemfiles/activerecord51.gemfile +7 -0
- data/gemfiles/activerecord52.gemfile +7 -0
- data/gemfiles/activerecord60.gemfile +7 -0
- data/lib/ar-multidb.rb +2 -0
- data/lib/multidb.rb +4 -0
- data/lib/multidb/balancer.rb +69 -68
- data/lib/multidb/candidate.rb +33 -0
- data/lib/multidb/configuration.rb +9 -12
- data/lib/multidb/log_subscriber.rb +23 -0
- data/lib/multidb/model_extensions.rb +16 -15
- data/lib/multidb/version.rb +4 -2
- data/spec/balancer_spec.rb +65 -21
- data/spec/helpers.rb +21 -18
- data/spec/spec_helper.rb +6 -3
- metadata +80 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 211ef81c6242f5424dbd0574b717bcd70d8f8cb4a7130198189d778491288000
|
4
|
+
data.tar.gz: 884334c8cd11d7a1715260f958304e08af23b6d7ce1129d88454b2acf979669f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f7f7bb26d97fe1ec7a835e6a3ddc9e360e3d444b69c3a0b49c4001b0d06887f8f62ee88bdfc15e336e967fc913bc4e040c761788560c46b4291990edcf7fcc3
|
7
|
+
data.tar.gz: 0d29556db56b3686666fe3378cb7fa7e2b5a3b8cca4798be7412af4dc93b685275e09118d187768168efc72a4f983170bd2a84d5f26a0b6f79c19d618431995c
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.4
|
3
|
+
Exclude:
|
4
|
+
- '**/vendor/**/*'
|
5
|
+
|
6
|
+
Layout/EmptyLinesAroundAttributeAccessor:
|
7
|
+
Enabled: true
|
8
|
+
Layout/SpaceAroundMethodCallOperator:
|
9
|
+
Enabled: true
|
10
|
+
Layout/LineLength:
|
11
|
+
Exclude:
|
12
|
+
- 'ar-multidb.gemspec'
|
13
|
+
Lint/DeprecatedOpenSSLConstant:
|
14
|
+
Enabled: true
|
15
|
+
Lint/DuplicateElsifCondition:
|
16
|
+
Enabled: true
|
17
|
+
Lint/MixedRegexpCaptureTypes:
|
18
|
+
Enabled: true
|
19
|
+
Lint/RaiseException:
|
20
|
+
Enabled: true
|
21
|
+
Lint/StructNewOverride:
|
22
|
+
Enabled: true
|
23
|
+
Naming/FileName:
|
24
|
+
Exclude:
|
25
|
+
- 'lib/ar-multidb.rb'
|
26
|
+
Metrics:
|
27
|
+
Enabled: false
|
28
|
+
Style/AccessorGrouping:
|
29
|
+
Enabled: true
|
30
|
+
Style/ArrayCoercion:
|
31
|
+
Enabled: true
|
32
|
+
Style/BisectedAttrAccessor:
|
33
|
+
Enabled: true
|
34
|
+
Style/CaseLikeIf:
|
35
|
+
Enabled: true
|
36
|
+
Style/Documentation:
|
37
|
+
Enabled: false
|
38
|
+
Style/ExponentialNotation:
|
39
|
+
Enabled: true
|
40
|
+
Style/HashAsLastArrayItem:
|
41
|
+
Enabled: true
|
42
|
+
Style/HashEachMethods:
|
43
|
+
Enabled: true
|
44
|
+
Style/HashLikeCase:
|
45
|
+
Enabled: true
|
46
|
+
Style/HashTransformKeys:
|
47
|
+
Enabled: true
|
48
|
+
Style/HashTransformValues:
|
49
|
+
Enabled: true
|
50
|
+
Style/RedundantAssignment:
|
51
|
+
Enabled: true
|
52
|
+
Style/RedundantFetchBlock:
|
53
|
+
Enabled: true
|
54
|
+
Style/RedundantFileExtensionInRequire:
|
55
|
+
Enabled: true
|
56
|
+
Style/RedundantRegexpCharacterClass:
|
57
|
+
Enabled: true
|
58
|
+
Style/RedundantRegexpEscape:
|
59
|
+
Enabled: true
|
60
|
+
Style/SlicingWithRange:
|
61
|
+
Enabled: true
|
62
|
+
|
data/.travis.yml
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
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
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,20 @@
|
|
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.0]
|
8
|
+
### Changed
|
9
|
+
- added rails 6 support
|
10
|
+
|
11
|
+
## [0.4.2]
|
12
|
+
### Changed
|
13
|
+
- adjust rails restriction to exclude untested rails 6
|
14
|
+
- adjust minimum ruby version to 2.4
|
15
|
+
- add rubocop
|
16
|
+
|
17
|
+
## [0.4.1]
|
18
|
+
### Added
|
19
|
+
- Added support for database aliases ( PR #26 )
|
20
|
+
|
data/Gemfile
CHANGED
@@ -1,9 +1,12 @@
|
|
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
|
-
|
7
|
-
|
8
|
-
|
8
|
+
local_gemfile = 'Gemfile.local'
|
9
|
+
|
10
|
+
if File.exist?(local_gemfile)
|
11
|
+
eval(File.read(local_gemfile)) # rubocop:disable Security/Eval
|
9
12
|
end
|
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,8 +14,13 @@ Randomized balancing of multiple connections within a group is supported. In the
|
|
14
14
|
|
15
15
|
## Requirements
|
16
16
|
|
17
|
-
* Ruby
|
18
|
-
* ActiveRecord
|
17
|
+
* Ruby 2.4 or later.
|
18
|
+
* ActiveRecord 5.1 or later.
|
19
|
+
|
20
|
+
## Older releases
|
21
|
+
For ActiveRecord 4. through 5.0 use version 0.3
|
22
|
+
For ActiveRecord older than 4.0 use the gem version 0.1.13
|
23
|
+
For ActiveRecord older than 3.0 use 0.1.10
|
19
24
|
|
20
25
|
## Comparison to other ActiveRecord extensions
|
21
26
|
|
@@ -27,10 +32,10 @@ Compared to other, more full-featured extensions such as Octopus and Seamless Da
|
|
27
32
|
|
28
33
|
**Orthogonal**. Unlike Octopus, for example, connections follow context:
|
29
34
|
|
30
|
-
Multidb.use(:
|
35
|
+
Multidb.use(:primary) do
|
31
36
|
@post = Post.find(1)
|
32
|
-
Multidb.use(:
|
33
|
-
@post.authors # This will use the
|
37
|
+
Multidb.use(:replica) do
|
38
|
+
@post.authors # This will use the replica
|
34
39
|
end
|
35
40
|
end
|
36
41
|
|
@@ -55,8 +60,8 @@ All that is needed is to set up your `database.yml` file:
|
|
55
60
|
host: db1
|
56
61
|
multidb:
|
57
62
|
databases:
|
58
|
-
|
59
|
-
host: db-
|
63
|
+
replica:
|
64
|
+
host: db-replica
|
60
65
|
|
61
66
|
Each database entry may be a hash or an array. So this also works:
|
62
67
|
|
@@ -68,24 +73,41 @@ Each database entry may be a hash or an array. So this also works:
|
|
68
73
|
host: db1
|
69
74
|
multidb:
|
70
75
|
databases:
|
71
|
-
|
72
|
-
- host: db-
|
73
|
-
- host: db-
|
76
|
+
replica:
|
77
|
+
- host: db-replica1
|
78
|
+
- host: db-replica2
|
74
79
|
|
75
80
|
If multiple elements are specified, Multidb will use the list to pick a random candidate connection.
|
76
81
|
|
77
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.
|
78
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
|
+
|
79
101
|
To use the connection, modify your code by wrapping database access logic in blocks:
|
80
102
|
|
81
|
-
Multidb.use(:
|
103
|
+
Multidb.use(:replica) do
|
82
104
|
@posts = Post.all
|
83
105
|
end
|
84
106
|
|
85
107
|
To wrap entire controller requests, for example:
|
86
108
|
|
87
109
|
class PostsController < ApplicationController
|
88
|
-
around_filter :
|
110
|
+
around_filter :run_using_replica, only: [:index]
|
89
111
|
|
90
112
|
def index
|
91
113
|
@posts = Post.all
|
@@ -95,22 +117,22 @@ To wrap entire controller requests, for example:
|
|
95
117
|
# Won't be wrapped
|
96
118
|
end
|
97
119
|
|
98
|
-
def
|
99
|
-
Multidb.use(:
|
120
|
+
def run_using_replica(&block)
|
121
|
+
Multidb.use(:replica, &block)
|
100
122
|
end
|
101
123
|
end
|
102
124
|
|
103
125
|
You can also set the current connection for the remainder of the thread's execution:
|
104
126
|
|
105
|
-
Multidb.use(:
|
127
|
+
Multidb.use(:replica)
|
106
128
|
# Do work
|
107
|
-
Multidb.use(:
|
129
|
+
Multidb.use(:primary)
|
108
130
|
|
109
131
|
Note that the symbol `:default` will (unless you override it) refer to the default top-level ActiveRecord configuration.
|
110
132
|
|
111
133
|
## Development mode
|
112
134
|
|
113
|
-
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.
|
114
136
|
|
115
137
|
If you are using Rails, this will be automatically enabled in `development` and `test` environments. Otherwise, simply set `fallback: true` in `database.yml`:
|
116
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,25 +1,28 @@
|
|
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.'
|
14
13
|
|
15
14
|
s.files = `git ls-files`.split("\n")
|
16
15
|
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 = [
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
|
19
|
+
s.required_ruby_version = '>= 2.4.0'
|
19
20
|
|
20
|
-
s.add_runtime_dependency '
|
21
|
-
s.add_runtime_dependency '
|
21
|
+
s.add_runtime_dependency 'activerecord', '>= 5.1', '< 6.1'
|
22
|
+
s.add_runtime_dependency 'activesupport', '>= 5.1', '< 6.1'
|
22
23
|
|
23
|
-
s.add_development_dependency '
|
24
|
-
s.add_development_dependency '
|
24
|
+
s.add_development_dependency 'rake', '~> 12.0'
|
25
|
+
s.add_development_dependency 'rspec', '~> 3.8'
|
26
|
+
s.add_development_dependency 'rubocop', '~> 0.88.0'
|
27
|
+
s.add_development_dependency 'sqlite3', '~> 1.3'
|
25
28
|
end
|
data/lib/ar-multidb.rb
CHANGED
data/lib/multidb.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_record'
|
2
4
|
|
3
5
|
require 'active_support/core_ext/module/delegation'
|
@@ -6,5 +8,7 @@ require 'active_support/core_ext/module/aliasing'
|
|
6
8
|
|
7
9
|
require_relative 'multidb/configuration'
|
8
10
|
require_relative 'multidb/model_extensions'
|
11
|
+
require_relative 'multidb/log_subscriber'
|
12
|
+
require_relative 'multidb/candidate'
|
9
13
|
require_relative 'multidb/balancer'
|
10
14
|
require_relative 'multidb/version'
|
data/lib/multidb/balancer.rb
CHANGED
@@ -1,108 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Multidb
|
4
|
+
class Balancer
|
5
|
+
attr_accessor :fallback
|
2
6
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
adapter = target[:adapter]
|
7
|
-
begin
|
8
|
-
require "active_record/connection_adapters/#{adapter}_adapter"
|
9
|
-
rescue LoadError
|
10
|
-
raise "Please install the #{adapter} adapter: `gem install activerecord-#{adapter}-adapter` (#{$!})"
|
11
|
-
end
|
12
|
-
if defined?(ActiveRecord::ConnectionAdapters::ConnectionSpecification)
|
13
|
-
spec_class = ActiveRecord::ConnectionAdapters::ConnectionSpecification
|
14
|
-
else
|
15
|
-
spec_class = ActiveRecord::Base::ConnectionSpecification
|
16
|
-
end
|
17
|
-
@connection_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(
|
18
|
-
spec_class.new(target, "#{adapter}_connection"))
|
19
|
-
else
|
20
|
-
@connection_pool = target
|
21
|
-
end
|
22
|
-
end
|
7
|
+
def initialize(configuration)
|
8
|
+
@candidates = {}.with_indifferent_access
|
9
|
+
@default_configuration = configuration
|
23
10
|
|
24
|
-
|
25
|
-
if block_given?
|
26
|
-
@connection_pool.with_connection(&block)
|
27
|
-
else
|
28
|
-
@connection_pool.connection
|
29
|
-
end
|
30
|
-
end
|
11
|
+
return unless @default_configuration
|
31
12
|
|
32
|
-
|
33
|
-
end
|
13
|
+
append(@default_configuration.raw_configuration[:databases] || {})
|
34
14
|
|
35
|
-
|
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
|
36
22
|
|
37
|
-
|
38
|
-
|
39
|
-
@
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
23
|
+
@default_candidate = Candidate.new('default', @default_configuration.default_handler)
|
24
|
+
|
25
|
+
@candidates[:default] = [@default_candidate] unless @candidates.include?(:default)
|
26
|
+
end
|
27
|
+
|
28
|
+
def append(databases)
|
29
|
+
databases.each_pair do |name, config|
|
30
|
+
configs = config.is_a?(Array) ? config : [config]
|
31
|
+
configs.each do |cfg|
|
32
|
+
if cfg['alias']
|
33
|
+
@candidates[name] = @candidates[cfg['alias']]
|
34
|
+
next
|
47
35
|
end
|
48
|
-
|
49
|
-
|
50
|
-
@
|
51
|
-
|
52
|
-
@fallback = %w(development test).include?(Rails.env)
|
53
|
-
else
|
54
|
-
@fallback = false
|
55
|
-
end
|
56
|
-
@default_candidate = Candidate.new(@configuration.default_pool)
|
57
|
-
unless @candidates.include?(:default)
|
58
|
-
@candidates[:default] = [@default_candidate]
|
36
|
+
|
37
|
+
candidate = Candidate.new(name, @default_configuration.default_adapter.merge(cfg))
|
38
|
+
@candidates[name] ||= []
|
39
|
+
@candidates[name].push(candidate)
|
59
40
|
end
|
60
41
|
end
|
61
42
|
end
|
62
43
|
|
63
44
|
def disconnect!
|
64
|
-
@candidates.values.flatten.each
|
65
|
-
candidate.connection_pool.disconnect!
|
66
|
-
end
|
45
|
+
@candidates.values.flatten.each(&:disconnect!)
|
67
46
|
end
|
68
47
|
|
69
|
-
def get(name, &
|
48
|
+
def get(name, &_block)
|
70
49
|
candidates = @candidates[name]
|
71
50
|
candidates ||= @fallback ? @candidates[:default] : []
|
51
|
+
|
72
52
|
raise ArgumentError, "No such database connection '#{name}'" if candidates.empty?
|
73
|
-
|
74
|
-
|
53
|
+
|
54
|
+
candidate = candidates.respond_to?(:sample) ? candidates.sample : candidates[rand(candidates.length)]
|
55
|
+
|
75
56
|
block_given? ? yield(candidate) : candidate
|
76
57
|
end
|
77
58
|
|
78
|
-
def use(name, &
|
59
|
+
def use(name, &_block)
|
79
60
|
result = nil
|
80
61
|
get(name) do |candidate|
|
81
62
|
if block_given?
|
82
63
|
candidate.connection do |connection|
|
83
|
-
|
84
|
-
|
64
|
+
previous_configuration = Thread.current[:multidb]
|
65
|
+
Thread.current[:multidb] = {
|
66
|
+
connection: connection,
|
67
|
+
connection_name: name
|
68
|
+
}
|
85
69
|
begin
|
86
70
|
result = yield
|
71
|
+
result = result.to_a if result.is_a?(ActiveRecord::Relation)
|
87
72
|
ensure
|
88
|
-
Thread.current[:
|
73
|
+
Thread.current[:multidb] = previous_configuration
|
89
74
|
end
|
90
75
|
result
|
91
76
|
end
|
92
77
|
else
|
93
|
-
|
78
|
+
Thread.current[:multidb] = {
|
79
|
+
connection: candidate.connection,
|
80
|
+
connection_name: name
|
81
|
+
}
|
82
|
+
result = candidate.connection
|
94
83
|
end
|
95
84
|
end
|
96
85
|
result
|
97
86
|
end
|
98
87
|
|
99
88
|
def current_connection
|
100
|
-
Thread.current[:
|
89
|
+
if Thread.current[:multidb]
|
90
|
+
Thread.current[:multidb][:connection]
|
91
|
+
else
|
92
|
+
@default_candidate.connection
|
93
|
+
end
|
101
94
|
end
|
102
95
|
|
103
|
-
|
104
|
-
|
96
|
+
def current_connection_name
|
97
|
+
if Thread.current[:multidb]
|
98
|
+
Thread.current[:multidb][:connection_name]
|
99
|
+
else
|
100
|
+
:default
|
101
|
+
end
|
102
|
+
end
|
105
103
|
|
104
|
+
class << self
|
106
105
|
def use(name, &block)
|
107
106
|
Multidb.balancer.use(name, &block)
|
108
107
|
end
|
@@ -111,11 +110,13 @@ module Multidb
|
|
111
110
|
Multidb.balancer.current_connection
|
112
111
|
end
|
113
112
|
|
113
|
+
def current_connection_name
|
114
|
+
Multidb.balancer.current_connection_name
|
115
|
+
end
|
116
|
+
|
114
117
|
def disconnect!
|
115
118
|
Multidb.balancer.disconnect!
|
116
119
|
end
|
117
120
|
end
|
118
|
-
|
119
121
|
end
|
120
|
-
|
121
|
-
end
|
122
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Multidb
|
4
|
+
class Candidate
|
5
|
+
def initialize(name, target)
|
6
|
+
@name = name
|
7
|
+
|
8
|
+
case target
|
9
|
+
when Hash
|
10
|
+
@connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
|
11
|
+
@connection_handler.establish_connection(target.merge(name: 'primary'))
|
12
|
+
when ActiveRecord::ConnectionAdapters::ConnectionHandler
|
13
|
+
@connection_handler = target
|
14
|
+
else
|
15
|
+
raise ArgumentError, 'Connection handler not passed to target'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def connection(&block)
|
20
|
+
if block_given?
|
21
|
+
@connection_handler.retrieve_connection_pool('primary').with_connection(&block)
|
22
|
+
else
|
23
|
+
@connection_handler.retrieve_connection('primary')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def disconnect!
|
28
|
+
@connection_handler.clear_all_connections!
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :name
|
32
|
+
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,34 +7,29 @@ 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.setup 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!
|
22
21
|
@balancer = nil
|
23
22
|
end
|
24
23
|
|
25
|
-
class NotInitializedError < StandardError; end
|
24
|
+
class NotInitializedError < StandardError; end
|
26
25
|
|
27
26
|
class Configuration
|
28
27
|
def initialize(default_adapter, configuration_hash)
|
29
|
-
@
|
28
|
+
@default_handler = ActiveRecord::Base.connection_handler
|
30
29
|
@default_adapter = default_adapter
|
31
30
|
@raw_configuration = configuration_hash
|
32
31
|
end
|
33
32
|
|
34
|
-
attr_reader :
|
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
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Multidb
|
4
|
+
module LogSubscriberExtension
|
5
|
+
def sql(event)
|
6
|
+
name = Multidb.balancer.current_connection_name
|
7
|
+
event.payload[:db_name] = name if name
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def debug(msg)
|
12
|
+
name = Multidb.balancer.current_connection_name
|
13
|
+
if name
|
14
|
+
db = color("[DB: #{name}]", ActiveSupport::LogSubscriber::GREEN, true)
|
15
|
+
super(db + msg)
|
16
|
+
else
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
ActiveRecord::LogSubscriber.prepend(Multidb::LogSubscriberExtension)
|
@@ -1,26 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_record/base'
|
2
4
|
|
3
5
|
module Multidb
|
6
|
+
module Connection
|
7
|
+
def establish_connection(spec = nil)
|
8
|
+
super(spec)
|
9
|
+
Multidb.init(connection_pool.spec.config)
|
10
|
+
end
|
11
|
+
|
12
|
+
def connection
|
13
|
+
Multidb.balancer.current_connection
|
14
|
+
rescue Multidb::NotInitializedError
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
4
19
|
module ModelExtensions
|
5
20
|
extend ActiveSupport::Concern
|
6
21
|
|
7
22
|
included do
|
8
23
|
class << self
|
9
|
-
|
10
|
-
alias_method_chain :connection, :multidb
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
module ClassMethods
|
15
|
-
def establish_connection_with_multidb(spec = nil)
|
16
|
-
establish_connection_without_multidb(spec)
|
17
|
-
Multidb.init(connection_pool.spec.config)
|
18
|
-
end
|
19
|
-
|
20
|
-
def connection_with_multidb
|
21
|
-
Multidb.balancer.current_connection
|
22
|
-
rescue Multidb::NotInitializedError
|
23
|
-
connection_without_multidb
|
24
|
+
prepend Multidb::Connection
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
data/lib/multidb/version.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
|
@@ -26,17 +27,46 @@ describe 'Multidb.balancer' do
|
|
26
27
|
|
27
28
|
Multidb.balancer.current_connection.should eq conn
|
28
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
|
29
59
|
end
|
30
60
|
|
31
61
|
describe '#use' do
|
32
62
|
context 'with configuration' do
|
33
63
|
before do
|
34
|
-
ActiveRecord::Base.establish_connection(
|
64
|
+
ActiveRecord::Base.establish_connection(configuration_with_replicas)
|
35
65
|
end
|
36
66
|
|
37
67
|
context 'undefined connection' do
|
38
68
|
it 'raises exception' do
|
39
|
-
|
69
|
+
lambda {
|
40
70
|
Multidb.use(:something) do
|
41
71
|
end
|
42
72
|
}.should raise_error(ArgumentError)
|
@@ -44,7 +74,7 @@ describe 'Multidb.balancer' do
|
|
44
74
|
end
|
45
75
|
|
46
76
|
it 'returns default connection on :default' do
|
47
|
-
|
77
|
+
ActiveRecord::Base.connection
|
48
78
|
Multidb.use(:default) do
|
49
79
|
conn2 = ActiveRecord::Base.connection
|
50
80
|
conn2.should eq Multidb.balancer.current_connection
|
@@ -55,61 +85,75 @@ describe 'Multidb.balancer' do
|
|
55
85
|
end
|
56
86
|
end
|
57
87
|
|
58
|
-
it 'returns
|
59
|
-
Multidb.use(:
|
88
|
+
it 'returns replica connection' do
|
89
|
+
Multidb.use(:replica1) do
|
60
90
|
conn = ActiveRecord::Base.connection
|
61
91
|
conn.should eq Multidb.balancer.current_connection
|
62
92
|
list = conn.execute('pragma database_list')
|
63
93
|
list.length.should eq 1
|
64
|
-
File.basename(list[0]['file']).should eq 'test-
|
94
|
+
File.basename(list[0]['file']).should eq 'test-replica1.sqlite'
|
65
95
|
end
|
66
96
|
end
|
67
97
|
|
68
|
-
it 'returns
|
69
|
-
|
70
|
-
|
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
|
71
111
|
conn = ActiveRecord::Base.connection
|
72
112
|
conn.should eq Multidb.balancer.current_connection
|
73
113
|
list = conn.execute('pragma database_list')
|
74
114
|
list.length.should eq 1
|
75
|
-
File.basename(list[0]['file']).should eq 'test-
|
115
|
+
File.basename(list[0]['file']).should eq 'test-replica2.sqlite'
|
76
116
|
end
|
77
117
|
end
|
78
118
|
end
|
79
119
|
|
80
120
|
it 'returns preserves state when nesting' do
|
81
|
-
Multidb.use(:
|
82
|
-
Multidb.use(:
|
121
|
+
Multidb.use(:replica1) do
|
122
|
+
Multidb.use(:replica2) do
|
83
123
|
conn = ActiveRecord::Base.connection
|
84
124
|
conn.should eq Multidb.balancer.current_connection
|
85
125
|
list = conn.execute('pragma database_list')
|
86
126
|
list.length.should eq 1
|
87
|
-
File.basename(list[0]['file']).should eq 'test-
|
127
|
+
File.basename(list[0]['file']).should eq 'test-replica2.sqlite'
|
88
128
|
end
|
89
129
|
|
90
130
|
conn = ActiveRecord::Base.connection
|
91
131
|
conn.should eq Multidb.balancer.current_connection
|
92
132
|
list = conn.execute('pragma database_list')
|
93
133
|
list.length.should eq 1
|
94
|
-
File.basename(list[0]['file']).should eq 'test-
|
134
|
+
File.basename(list[0]['file']).should eq 'test-replica1.sqlite'
|
95
135
|
end
|
96
136
|
end
|
97
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
|
+
|
98
143
|
it 'returns random candidate' do
|
99
144
|
names = []
|
100
145
|
100.times do
|
101
|
-
Multidb.use(:
|
146
|
+
Multidb.use(:replica3) do
|
102
147
|
list = ActiveRecord::Base.connection.execute('pragma database_list')
|
103
148
|
list.length.should eq 1
|
104
149
|
names.push(File.basename(list[0]['file']))
|
105
150
|
end
|
106
151
|
end
|
107
152
|
names.sort.uniq.should eq [
|
108
|
-
'test-
|
109
|
-
'test-
|
153
|
+
'test-replica3-1.sqlite',
|
154
|
+
'test-replica3-2.sqlite'
|
110
155
|
]
|
111
156
|
end
|
112
157
|
end
|
113
158
|
end
|
114
|
-
|
115
|
-
end
|
159
|
+
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,23 +1,26 @@
|
|
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'
|
12
14
|
|
13
15
|
RSpec.configure do |config|
|
14
16
|
config.include Helpers
|
17
|
+
config.expect_with(:rspec) { |c| c.syntax = :should }
|
15
18
|
config.before :each do
|
16
19
|
ActiveRecord::Base.clear_all_connections!
|
17
20
|
Multidb.reset!
|
18
21
|
end
|
19
22
|
config.after :each do
|
20
|
-
Dir.glob(File.expand_path('
|
23
|
+
Dir.glob(File.expand_path('test*.sqlite', __dir__)).each do |f|
|
21
24
|
FileUtils.rm(f)
|
22
25
|
end
|
23
26
|
end
|
metadata
CHANGED
@@ -1,90 +1,139 @@
|
|
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.0
|
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-06-08 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
|
-
version: '
|
20
|
+
version: '5.1'
|
21
|
+
- - "<"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '6.1'
|
20
24
|
type: :runtime
|
21
25
|
prerelease: false
|
22
26
|
version_requirements: !ruby/object:Gem::Requirement
|
23
27
|
requirements:
|
24
|
-
- -
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '5.1'
|
31
|
+
- - "<"
|
25
32
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
33
|
+
version: '6.1'
|
27
34
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
35
|
+
name: activesupport
|
29
36
|
requirement: !ruby/object:Gem::Requirement
|
30
37
|
requirements:
|
31
|
-
- -
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.1'
|
41
|
+
- - "<"
|
32
42
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
43
|
+
version: '6.1'
|
34
44
|
type: :runtime
|
35
45
|
prerelease: false
|
36
46
|
version_requirements: !ruby/object:Gem::Requirement
|
37
47
|
requirements:
|
38
|
-
- -
|
48
|
+
- - ">="
|
39
49
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
50
|
+
version: '5.1'
|
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
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '12.0'
|
41
68
|
- !ruby/object:Gem::Dependency
|
42
69
|
name: rspec
|
43
70
|
requirement: !ruby/object:Gem::Requirement
|
44
71
|
requirements:
|
45
|
-
- -
|
72
|
+
- - "~>"
|
46
73
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
74
|
+
version: '3.8'
|
48
75
|
type: :development
|
49
76
|
prerelease: false
|
50
77
|
version_requirements: !ruby/object:Gem::Requirement
|
51
78
|
requirements:
|
52
|
-
- -
|
79
|
+
- - "~>"
|
53
80
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
81
|
+
version: '3.8'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: rubocop
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 0.88.0
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 0.88.0
|
55
96
|
- !ruby/object:Gem::Dependency
|
56
97
|
name: sqlite3
|
57
98
|
requirement: !ruby/object:Gem::Requirement
|
58
99
|
requirements:
|
59
|
-
- -
|
100
|
+
- - "~>"
|
60
101
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
102
|
+
version: '1.3'
|
62
103
|
type: :development
|
63
104
|
prerelease: false
|
64
105
|
version_requirements: !ruby/object:Gem::Requirement
|
65
106
|
requirements:
|
66
|
-
- -
|
107
|
+
- - "~>"
|
67
108
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
109
|
+
version: '1.3'
|
69
110
|
description: Multidb is an ActiveRecord extension for switching between multiple database
|
70
|
-
connections, such as
|
111
|
+
connections, such as primary/replica setups.
|
71
112
|
email:
|
72
113
|
- alex@bengler.no
|
114
|
+
- urkle@outoforder.cc
|
73
115
|
executables: []
|
74
116
|
extensions: []
|
75
117
|
extra_rdoc_files: []
|
76
118
|
files:
|
77
|
-
- .gitignore
|
78
|
-
- .
|
119
|
+
- ".gitignore"
|
120
|
+
- ".rubocop.yml"
|
121
|
+
- ".travis.yml"
|
122
|
+
- CHANGELOG.md
|
79
123
|
- Gemfile
|
80
124
|
- LICENSE
|
81
125
|
- README.markdown
|
82
126
|
- Rakefile
|
83
127
|
- ar-multidb.gemspec
|
128
|
+
- gemfiles/activerecord51.gemfile
|
129
|
+
- gemfiles/activerecord52.gemfile
|
130
|
+
- gemfiles/activerecord60.gemfile
|
84
131
|
- lib/ar-multidb.rb
|
85
132
|
- lib/multidb.rb
|
86
133
|
- lib/multidb/balancer.rb
|
134
|
+
- lib/multidb/candidate.rb
|
87
135
|
- lib/multidb/configuration.rb
|
136
|
+
- lib/multidb/log_subscriber.rb
|
88
137
|
- lib/multidb/model_extensions.rb
|
89
138
|
- lib/multidb/version.rb
|
90
139
|
- spec/balancer_spec.rb
|
@@ -93,29 +142,27 @@ files:
|
|
93
142
|
homepage: ''
|
94
143
|
licenses: []
|
95
144
|
metadata: {}
|
96
|
-
post_install_message:
|
145
|
+
post_install_message:
|
97
146
|
rdoc_options: []
|
98
147
|
require_paths:
|
99
148
|
- lib
|
100
149
|
required_ruby_version: !ruby/object:Gem::Requirement
|
101
150
|
requirements:
|
102
|
-
- -
|
151
|
+
- - ">="
|
103
152
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
153
|
+
version: 2.4.0
|
105
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
155
|
requirements:
|
107
|
-
- -
|
156
|
+
- - ">="
|
108
157
|
- !ruby/object:Gem::Version
|
109
158
|
version: '0'
|
110
159
|
requirements: []
|
111
|
-
|
112
|
-
|
113
|
-
signing_key:
|
160
|
+
rubygems_version: 3.1.6
|
161
|
+
signing_key:
|
114
162
|
specification_version: 4
|
115
163
|
summary: Multidb is an ActiveRecord extension for switching between multiple database
|
116
|
-
connections, such as
|
164
|
+
connections, such as primary/replica setups.
|
117
165
|
test_files:
|
118
166
|
- spec/balancer_spec.rb
|
119
167
|
- spec/helpers.rb
|
120
168
|
- spec/spec_helper.rb
|
121
|
-
has_rdoc:
|