ar-multidb 0.1.10 → 0.1.11
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 +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +54 -0
- data/README.markdown +44 -56
- data/Rakefile +5 -0
- data/ar-multidb.gemspec +6 -3
- data/lib/ar-multidb.rb +1 -1
- data/lib/multidb.rb +7 -25
- data/lib/multidb/balancer.rb +16 -15
- data/lib/multidb/configuration.rb +39 -17
- data/lib/multidb/model_extensions.rb +15 -14
- data/lib/multidb/version.rb +1 -1
- data/spec/balancer_spec.rb +115 -0
- data/spec/helpers.rb +20 -0
- data/spec/spec_helper.rb +24 -0
- metadata +53 -24
- data/init.rb +0 -2
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 717edcedfa1c1db819f4b05fadc4e56017eff646
|
4
|
+
data.tar.gz: 5f5afdffc350920bd0774ae5e13b533e396781be
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 32bc26a45bcbaa7e46b0649dff1ae7a0b9c9376a126ba438ec9c3a689f1ede815cb2f1109fffa2c2ce9a3c01d35c5658265422f3ec2ad42f55db2f704a429030
|
7
|
+
data.tar.gz: e7d1c10d442625f0d56441494651cea2a209700f55f32c595c32fa5bd1407bb47a6ad7a2f793c0a275b27ff9c64096b8f1fb0f92722509989d7c812a65c9663a
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ar-multidb (0.1.10)
|
5
|
+
activerecord (>= 3.0)
|
6
|
+
activesupport (>= 3.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activemodel (4.0.2)
|
12
|
+
activesupport (= 4.0.2)
|
13
|
+
builder (~> 3.1.0)
|
14
|
+
activerecord (4.0.2)
|
15
|
+
activemodel (= 4.0.2)
|
16
|
+
activerecord-deprecated_finders (~> 1.0.2)
|
17
|
+
activesupport (= 4.0.2)
|
18
|
+
arel (~> 4.0.0)
|
19
|
+
activerecord-deprecated_finders (1.0.3)
|
20
|
+
activesupport (4.0.2)
|
21
|
+
i18n (~> 0.6, >= 0.6.4)
|
22
|
+
minitest (~> 4.2)
|
23
|
+
multi_json (~> 1.3)
|
24
|
+
thread_safe (~> 0.1)
|
25
|
+
tzinfo (~> 0.3.37)
|
26
|
+
arel (4.0.1)
|
27
|
+
atomic (1.1.14)
|
28
|
+
builder (3.1.4)
|
29
|
+
diff-lcs (1.2.5)
|
30
|
+
i18n (0.6.9)
|
31
|
+
minitest (4.7.5)
|
32
|
+
multi_json (1.8.4)
|
33
|
+
rake (10.1.0)
|
34
|
+
rspec (2.14.1)
|
35
|
+
rspec-core (~> 2.14.0)
|
36
|
+
rspec-expectations (~> 2.14.0)
|
37
|
+
rspec-mocks (~> 2.14.0)
|
38
|
+
rspec-core (2.14.7)
|
39
|
+
rspec-expectations (2.14.5)
|
40
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
41
|
+
rspec-mocks (2.14.5)
|
42
|
+
sqlite3 (1.3.8)
|
43
|
+
thread_safe (0.1.3)
|
44
|
+
atomic
|
45
|
+
tzinfo (0.3.38)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
ruby
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
ar-multidb!
|
52
|
+
rake
|
53
|
+
rspec
|
54
|
+
sqlite3
|
data/README.markdown
CHANGED
@@ -1,35 +1,31 @@
|
|
1
|
-
|
2
|
-
=======
|
1
|
+
[](https://travis-ci.org/atombender/multidb)
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
# Multidb
|
4
|
+
|
5
|
+
A simple, no-nonsense ActiveRecord extension which allows the application to switch between multiple database connections, such as in a master/slave environment. For example:
|
6
6
|
|
7
7
|
Multidb.use(:slave) do
|
8
8
|
@posts = Post.all
|
9
9
|
end
|
10
|
-
|
11
|
-
The extension was developed in order to support PostgreSQL 9.0's new hot standby
|
12
|
-
support in a production environment.
|
13
10
|
|
14
|
-
|
15
|
-
|
11
|
+
The extension was developed in order to support PostgreSQL 9.0's new hot standby support in a production environment.
|
12
|
+
|
13
|
+
Randomized balancing of multiple connections within a group is supported. In the future, some kind of automatic balancing of read/write queries could be implemented.
|
16
14
|
|
17
|
-
|
15
|
+
## Requirements
|
18
16
|
|
17
|
+
* Ruby 1.9.3 or later.
|
18
|
+
* ActiveRecord 3.0 or later. (Earlier versions can use the gem version 0.1.10.)
|
19
19
|
|
20
|
-
Comparison to other ActiveRecord extensions
|
21
|
-
===========================================
|
20
|
+
## Comparison to other ActiveRecord extensions
|
22
21
|
|
23
22
|
Compared to other, more full-featured extensions such as Octopus and Seamless Database Pool:
|
24
23
|
|
25
|
-
**Minimal amount of monkeypatching magic**. The only part of ActiveRecord that is overridden is
|
26
|
-
`ActiveRecord::Base#connection`.
|
24
|
+
**Minimal amount of monkeypatching magic**. The only part of ActiveRecord that is overridden is `ActiveRecord::Base#connection`.
|
27
25
|
|
28
|
-
**Non-invasive**. Very small amounts of configuration and changes to the client
|
29
|
-
application are required.
|
26
|
+
**Non-invasive**. Very small amounts of configuration and changes to the client application are required.
|
30
27
|
|
31
|
-
**Orthogonal**. Unlike Octopus, for example, connections follow
|
32
|
-
context:
|
28
|
+
**Orthogonal**. Unlike Octopus, for example, connections follow context:
|
33
29
|
|
34
30
|
Multidb.use(:master) do
|
35
31
|
@post = Post.find(1)
|
@@ -38,29 +34,17 @@ context:
|
|
38
34
|
end
|
39
35
|
end
|
40
36
|
|
41
|
-
**Low-overhead**. Since `connection` is called on every single
|
42
|
-
database operation, it needs to be fast. Which it is: Multidb's implementation of
|
37
|
+
**Low-overhead**. Since `connection` is called on every single database operation, it needs to be fast. Which it is: Multidb's implementation of
|
43
38
|
`connection` incurs only a single hash lookup in `Thread.current`.
|
44
39
|
|
45
|
-
However, Multidb also has fewer features. At the moment it will _not_ automatically
|
46
|
-
split reads and writes between database backends.
|
47
|
-
|
40
|
+
However, Multidb also has fewer features. At the moment it will _not_ automatically split reads and writes between database backends.
|
48
41
|
|
49
|
-
Getting started
|
50
|
-
===============
|
42
|
+
## Getting started
|
51
43
|
|
52
|
-
|
53
|
-
|
54
|
-
config.gem 'ar-multidb'
|
55
|
-
|
56
|
-
In Bundler-based on Rails apps, add this to your `Gemfile`:
|
44
|
+
Add to your `Gemfile`:
|
57
45
|
|
58
46
|
gem 'ar-multidb', :require => 'multidb'
|
59
47
|
|
60
|
-
You may also install it as a plugin:
|
61
|
-
|
62
|
-
script/plugin install git://github.com/alexstaubo/multidb.git
|
63
|
-
|
64
48
|
All that is needed is to set up your `database.yml` file:
|
65
49
|
|
66
50
|
production:
|
@@ -87,47 +71,48 @@ Each database entry may be a hash or an array. So this also works:
|
|
87
71
|
slave:
|
88
72
|
- host: db-slave1
|
89
73
|
- host: db-slave2
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
and so on.
|
74
|
+
|
75
|
+
If multiple elements are specified, Multidb will use the list to pick a random candidate connection.
|
76
|
+
|
77
|
+
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.
|
94
78
|
|
95
79
|
To use the connection, modify your code by wrapping database access logic in blocks:
|
96
80
|
|
97
81
|
Multidb.use(:slave) do
|
98
82
|
@posts = Post.all
|
99
83
|
end
|
100
|
-
|
84
|
+
|
101
85
|
To wrap entire controller requests, for example:
|
102
86
|
|
103
87
|
class PostsController < ApplicationController
|
104
|
-
around_filter :run_using_slave
|
105
|
-
|
88
|
+
around_filter :run_using_slave, only: [:index]
|
89
|
+
|
90
|
+
def index
|
91
|
+
@posts = Post.all
|
92
|
+
end
|
93
|
+
|
94
|
+
def edit
|
95
|
+
# Won't be wrapped
|
96
|
+
end
|
97
|
+
|
106
98
|
def run_using_slave(&block)
|
107
99
|
Multidb.use(:slave, &block)
|
108
100
|
end
|
109
101
|
end
|
110
|
-
|
102
|
+
|
111
103
|
You can also set the current connection for the remainder of the thread's execution:
|
112
104
|
|
113
105
|
Multidb.use(:slave)
|
114
106
|
# Do work
|
115
107
|
Multidb.use(:master)
|
116
108
|
|
117
|
-
Note that the symbol `:default` will (unless you override it) refer to the default
|
118
|
-
top-level ActiveRecord configuration.
|
119
|
-
|
109
|
+
Note that the symbol `:default` will (unless you override it) refer to the default top-level ActiveRecord configuration.
|
120
110
|
|
121
|
-
Development mode
|
122
|
-
================
|
111
|
+
## Development mode
|
123
112
|
|
124
|
-
In development you will typically want `Multidb.use(:slave)` to still work, but you
|
125
|
-
probably don't want to run multiple databases on your development box. To make `use`
|
126
|
-
silently fall back to using the default connection, Multidb can run in fallback
|
127
|
-
mode.
|
113
|
+
In development you will typically want `Multidb.use(:slave)` 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.
|
128
114
|
|
129
|
-
If you are using Rails, this will be automatically enabled in
|
130
|
-
'test' environments. Otherwise, simply set `fallback: true` in `database.yml`:
|
115
|
+
If you are using Rails, this will be automatically enabled in `development` and `test` environments. Otherwise, simply set `fallback: true` in `database.yml`:
|
131
116
|
|
132
117
|
development:
|
133
118
|
adapter: postgresql
|
@@ -138,7 +123,10 @@ If you are using Rails, this will be automatically enabled in 'development' and
|
|
138
123
|
multidb:
|
139
124
|
fallback: true
|
140
125
|
|
141
|
-
|
142
|
-
|
126
|
+
## Limitations
|
127
|
+
|
128
|
+
Multidb does not support per-class connections (eg., calling `establish_connection` within a class, as opposed to `ActiveRecord::Base`).
|
129
|
+
|
130
|
+
## Legal
|
143
131
|
|
144
|
-
Copyright (c) 2011 Alexander Staubo. Released under the MIT license. See the file LICENSE
|
132
|
+
Copyright (c) 2011-2014 Alexander Staubo. Released under the MIT license. See the file `LICENSE`.
|
data/Rakefile
CHANGED
data/ar-multidb.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = "ar-multidb"
|
7
7
|
s.version = Multidb::VERSION
|
8
8
|
s.authors = ["Alexander Staubo"]
|
9
|
-
s.email = ["alex@
|
9
|
+
s.email = ["alex@bengler.no"]
|
10
10
|
s.homepage = ""
|
11
11
|
s.summary = s.description = %q{Multidb is an ActiveRecord extension for switching between multiple database connections, such as master/slave setups.}
|
12
12
|
|
@@ -17,6 +17,9 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
|
-
s.add_runtime_dependency 'activesupport', '>=
|
21
|
-
s.add_runtime_dependency 'activerecord', '>=
|
20
|
+
s.add_runtime_dependency 'activesupport', '>= 3.0'
|
21
|
+
s.add_runtime_dependency 'activerecord', '>= 3.0'
|
22
|
+
|
23
|
+
s.add_development_dependency 'rspec'
|
24
|
+
s.add_development_dependency 'sqlite3'
|
22
25
|
end
|
data/lib/ar-multidb.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
require_relative 'multidb'
|
data/lib/multidb.rb
CHANGED
@@ -1,28 +1,10 @@
|
|
1
1
|
require 'active_record'
|
2
|
-
require 'active_support/core_ext/module/delegation'
|
3
|
-
|
4
|
-
require 'multidb/configuration'
|
5
|
-
require 'multidb/model_extensions'
|
6
|
-
require 'multidb/balancer'
|
7
|
-
|
8
|
-
module Multidb
|
9
|
-
class << self
|
10
|
-
|
11
|
-
def install!
|
12
|
-
configure!
|
13
|
-
if @configuration and not @configuration.raw_configuration[:databases].blank?
|
14
|
-
ActiveRecord::Base.class_eval do
|
15
|
-
include Multidb::ModelExtensions
|
16
|
-
end
|
17
|
-
end
|
18
|
-
@balancer = Balancer.new(@configuration)
|
19
|
-
end
|
20
|
-
|
21
|
-
attr_reader :balancer
|
22
2
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
3
|
+
require 'active_support/core_ext/module/delegation'
|
4
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
5
|
+
require 'active_support/core_ext/module/aliasing'
|
27
6
|
|
28
|
-
|
7
|
+
require_relative 'multidb/configuration'
|
8
|
+
require_relative 'multidb/model_extensions'
|
9
|
+
require_relative 'multidb/balancer'
|
10
|
+
require_relative 'multidb/version'
|
data/lib/multidb/balancer.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Multidb
|
2
|
-
|
2
|
+
|
3
3
|
class Candidate
|
4
4
|
def initialize(target)
|
5
5
|
if target.is_a?(Hash)
|
@@ -10,12 +10,12 @@ module Multidb
|
|
10
10
|
raise "Please install the #{adapter} adapter: `gem install activerecord-#{adapter}-adapter` (#{$!})"
|
11
11
|
end
|
12
12
|
@connection_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new(
|
13
|
-
ActiveRecord::
|
13
|
+
ActiveRecord::ConnectionAdapters::ConnectionSpecification.new(target, "#{adapter}_connection"))
|
14
14
|
else
|
15
15
|
@connection_pool = target
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def connection(&block)
|
20
20
|
if block_given?
|
21
21
|
@connection_pool.with_connection(&block)
|
@@ -26,16 +26,16 @@ module Multidb
|
|
26
26
|
|
27
27
|
attr_reader :connection_pool
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
class Balancer
|
31
|
-
|
31
|
+
|
32
32
|
def initialize(configuration)
|
33
33
|
@candidates = {}.with_indifferent_access
|
34
34
|
@configuration = configuration
|
35
35
|
if @configuration
|
36
36
|
(@configuration.raw_configuration[:databases] || {}).each_pair do |name, config|
|
37
37
|
configs = config.is_a?(Array) ? config : [config]
|
38
|
-
configs.each do |config|
|
38
|
+
configs.each do |config|
|
39
39
|
candidate = Candidate.new(@configuration.default_adapter.merge(config))
|
40
40
|
@candidates[name] ||= []
|
41
41
|
@candidates[name].push(candidate)
|
@@ -65,17 +65,17 @@ module Multidb
|
|
65
65
|
candidates = @candidates[name]
|
66
66
|
candidates ||= @fallback ? @candidates[:default] : []
|
67
67
|
raise ArgumentError, "No such database connection '#{name}'" if candidates.empty?
|
68
|
-
candidate = candidates.respond_to?(:sample) ?
|
68
|
+
candidate = candidates.respond_to?(:sample) ?
|
69
69
|
candidates.sample : candidates[rand(candidates.length)]
|
70
70
|
block_given? ? yield(candidate) : candidate
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
def use(name, &block)
|
74
74
|
result = nil
|
75
75
|
get(name) do |candidate|
|
76
76
|
if block_given?
|
77
77
|
candidate.connection do |connection|
|
78
|
-
previous_connection, Thread.current[:multidb_connection] =
|
78
|
+
previous_connection, Thread.current[:multidb_connection] =
|
79
79
|
Thread.current[:multidb_connection], connection
|
80
80
|
begin
|
81
81
|
result = yield
|
@@ -90,16 +90,17 @@ module Multidb
|
|
90
90
|
end
|
91
91
|
result
|
92
92
|
end
|
93
|
-
|
93
|
+
|
94
94
|
def current_connection
|
95
95
|
Thread.current[:multidb_connection] || @default_candidate.connection
|
96
96
|
end
|
97
|
-
|
97
|
+
|
98
98
|
class << self
|
99
|
+
delegate :use, :current_connection, :disconnect!, to: :balancer
|
99
100
|
def use(name, &block)
|
100
101
|
Multidb.balancer.use(name, &block)
|
101
102
|
end
|
102
|
-
|
103
|
+
|
103
104
|
def current_connection
|
104
105
|
Multidb.balancer.current_connection
|
105
106
|
end
|
@@ -108,7 +109,7 @@ module Multidb
|
|
108
109
|
Multidb.balancer.disconnect!
|
109
110
|
end
|
110
111
|
end
|
111
|
-
|
112
|
+
|
112
113
|
end
|
113
|
-
|
114
|
-
end
|
114
|
+
|
115
|
+
end
|
@@ -1,22 +1,19 @@
|
|
1
1
|
module Multidb
|
2
|
-
|
2
|
+
|
3
|
+
mattr_reader :configuration
|
4
|
+
|
3
5
|
class << self
|
4
|
-
|
5
|
-
|
6
|
-
connection_pool = ActiveRecord::Base.connection_pool
|
7
|
-
if connection_pool
|
8
|
-
connection = connection_pool.connection
|
9
|
-
activerecord_config = connection.instance_variable_get(:@config).dup.with_indifferent_access
|
10
|
-
default_adapter, configuration_hash = activerecord_config, activerecord_config.delete(:multidb)
|
11
|
-
configuration_hash ||= {}
|
12
|
-
@configuration = Configuration.new(default_adapter, configuration_hash)
|
13
|
-
end
|
14
|
-
end
|
6
|
+
delegate :use, :get, :disconnect!, to: :balancer
|
7
|
+
end
|
15
8
|
|
16
|
-
|
17
|
-
|
9
|
+
def self.balancer
|
10
|
+
@balancer ||= create_balancer
|
18
11
|
end
|
19
|
-
|
12
|
+
|
13
|
+
def self.reset!
|
14
|
+
@balancer, @configuration = nil, nil
|
15
|
+
end
|
16
|
+
|
20
17
|
class Configuration
|
21
18
|
def initialize(default_adapter, configuration_hash)
|
22
19
|
@default_pool = ActiveRecord::Base.connection_pool
|
@@ -28,5 +25,30 @@ module Multidb
|
|
28
25
|
attr_reader :default_adapter
|
29
26
|
attr_reader :raw_configuration
|
30
27
|
end
|
31
|
-
|
32
|
-
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def self.create_balancer
|
32
|
+
unless @configuration
|
33
|
+
begin
|
34
|
+
connection_pool = ActiveRecord::Base.connection_pool
|
35
|
+
rescue ActiveRecord::ConnectionNotEstablished
|
36
|
+
# Ignore
|
37
|
+
else
|
38
|
+
connection = connection_pool.connection
|
39
|
+
|
40
|
+
# FIXME: This is hacky, but apparently the only way to get at
|
41
|
+
# the internal configuration hash.
|
42
|
+
activerecord_config = connection.instance_variable_get(:@config).dup.with_indifferent_access
|
43
|
+
|
44
|
+
default_adapter, configuration_hash = activerecord_config, activerecord_config.delete(:multidb)
|
45
|
+
|
46
|
+
@configuration = Configuration.new(default_adapter, configuration_hash || {})
|
47
|
+
end
|
48
|
+
end
|
49
|
+
if @configuration
|
50
|
+
Balancer.new(@configuration)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -1,26 +1,27 @@
|
|
1
1
|
module Multidb
|
2
2
|
module ModelExtensions
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
class << self
|
10
|
-
alias_method_chain :connection, :multidb
|
11
|
-
end
|
12
|
-
end
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
class << self
|
8
|
+
alias_method_chain :connection, :multidb
|
13
9
|
end
|
14
10
|
end
|
15
11
|
|
16
12
|
module ClassMethods
|
17
13
|
def connection_with_multidb
|
18
|
-
Multidb.balancer
|
14
|
+
if (balancer = Multidb.balancer)
|
15
|
+
balancer.current_connection
|
16
|
+
else
|
17
|
+
connection_without_multidb
|
18
|
+
end
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
module InstanceMethods
|
23
|
-
end
|
24
|
-
|
25
22
|
end
|
26
23
|
end
|
24
|
+
|
25
|
+
ActiveRecord::Base.class_eval do
|
26
|
+
include Multidb::ModelExtensions
|
27
|
+
end
|
data/lib/multidb/version.rb
CHANGED
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Multidb.balancer' do
|
4
|
+
|
5
|
+
context 'with no configuration' do
|
6
|
+
it 'returns nothing' do
|
7
|
+
Multidb.balancer.should eq nil
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'with configuration' do
|
12
|
+
before do
|
13
|
+
ActiveRecord::Base.establish_connection(configuration_with_slaves)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns balancer' do
|
17
|
+
Multidb.balancer.should_not eq nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns main connection by default' do
|
21
|
+
conn = ActiveRecord::Base.connection
|
22
|
+
|
23
|
+
list = conn.execute('pragma database_list')
|
24
|
+
list.length.should eq 1
|
25
|
+
File.basename(list[0]['file']).should eq 'test.sqlite'
|
26
|
+
|
27
|
+
Multidb.balancer.current_connection.should eq conn
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#use' do
|
32
|
+
context 'with no configuration' do
|
33
|
+
it 'raises exception' do
|
34
|
+
-> {
|
35
|
+
Multidb.use(:something) do
|
36
|
+
end
|
37
|
+
}.should raise_error(ArgumentError)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with configuration' do
|
42
|
+
before do
|
43
|
+
ActiveRecord::Base.establish_connection(configuration_with_slaves)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns default connection on :default' do
|
47
|
+
conn = ActiveRecord::Base.connection
|
48
|
+
Multidb.use(:default) do
|
49
|
+
conn2 = ActiveRecord::Base.connection
|
50
|
+
conn2.should eq Multidb.balancer.current_connection
|
51
|
+
|
52
|
+
list = conn2.execute('pragma database_list')
|
53
|
+
list.length.should eq 1
|
54
|
+
File.basename(list[0]['file']).should eq 'test.sqlite'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'returns slave connection' do
|
59
|
+
Multidb.use(:slave1) do
|
60
|
+
conn = ActiveRecord::Base.connection
|
61
|
+
conn.should eq Multidb.balancer.current_connection
|
62
|
+
list = conn.execute('pragma database_list')
|
63
|
+
list.length.should eq 1
|
64
|
+
File.basename(list[0]['file']).should eq 'test-slave1.sqlite'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'returns supports nested slave connection' do
|
69
|
+
Multidb.use(:slave1) do
|
70
|
+
Multidb.use(:slave2) do
|
71
|
+
conn = ActiveRecord::Base.connection
|
72
|
+
conn.should eq Multidb.balancer.current_connection
|
73
|
+
list = conn.execute('pragma database_list')
|
74
|
+
list.length.should eq 1
|
75
|
+
File.basename(list[0]['file']).should eq 'test-slave2.sqlite'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'returns preserves state when nesting' do
|
81
|
+
Multidb.use(:slave1) do
|
82
|
+
Multidb.use(:slave2) do
|
83
|
+
conn = ActiveRecord::Base.connection
|
84
|
+
conn.should eq Multidb.balancer.current_connection
|
85
|
+
list = conn.execute('pragma database_list')
|
86
|
+
list.length.should eq 1
|
87
|
+
File.basename(list[0]['file']).should eq 'test-slave2.sqlite'
|
88
|
+
end
|
89
|
+
|
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-slave1.sqlite'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'returns random candidate' do
|
99
|
+
names = []
|
100
|
+
100.times do
|
101
|
+
Multidb.use(:slave3) do
|
102
|
+
list = ActiveRecord::Base.connection.execute('pragma database_list')
|
103
|
+
list.length.should eq 1
|
104
|
+
names.push(File.basename(list[0]['file']))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
names.sort.uniq.should eq [
|
108
|
+
'test-slave3-1.sqlite',
|
109
|
+
'test-slave3-2.sqlite'
|
110
|
+
]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
data/spec/helpers.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Helpers
|
2
|
+
|
3
|
+
def configuration_with_slaves
|
4
|
+
return YAML.load(<<-end)
|
5
|
+
adapter: sqlite3
|
6
|
+
database: spec/test.sqlite
|
7
|
+
encoding: utf-8
|
8
|
+
multidb:
|
9
|
+
databases:
|
10
|
+
slave1:
|
11
|
+
database: spec/test-slave1.sqlite
|
12
|
+
slave2:
|
13
|
+
database: spec/test-slave2.sqlite
|
14
|
+
slave3:
|
15
|
+
- database: spec/test-slave3-1.sqlite
|
16
|
+
- database: spec/test-slave3-2.sqlite
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
environment = ENV['RACK_ENV'] ||= 'test'
|
2
|
+
|
3
|
+
require 'rspec'
|
4
|
+
require 'yaml'
|
5
|
+
require 'active_record'
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
9
|
+
require 'multidb'
|
10
|
+
|
11
|
+
require_relative 'helpers'
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.include Helpers
|
15
|
+
config.before :each do
|
16
|
+
ActiveRecord::Base.clear_all_connections!
|
17
|
+
Multidb.reset!
|
18
|
+
end
|
19
|
+
config.after :each do
|
20
|
+
Dir.glob(File.expand_path('../test*.sqlite', __FILE__)).each do |f|
|
21
|
+
FileUtils.rm(f)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
CHANGED
@@ -1,93 +1,122 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ar-multidb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.11
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Alexander Staubo
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-02-02 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: activesupport
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: '
|
19
|
+
version: '3.0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
26
|
+
version: '3.0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: activerecord
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
|
-
version: '
|
33
|
+
version: '3.0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
|
-
version: '
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sqlite3
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
46
69
|
description: Multidb is an ActiveRecord extension for switching between multiple database
|
47
70
|
connections, such as master/slave setups.
|
48
71
|
email:
|
49
|
-
- alex@
|
72
|
+
- alex@bengler.no
|
50
73
|
executables: []
|
51
74
|
extensions: []
|
52
75
|
extra_rdoc_files: []
|
53
76
|
files:
|
54
77
|
- .gitignore
|
78
|
+
- .travis.yml
|
55
79
|
- Gemfile
|
80
|
+
- Gemfile.lock
|
56
81
|
- LICENSE
|
57
82
|
- README.markdown
|
58
83
|
- Rakefile
|
59
84
|
- ar-multidb.gemspec
|
60
|
-
- init.rb
|
61
85
|
- lib/ar-multidb.rb
|
62
86
|
- lib/multidb.rb
|
63
87
|
- lib/multidb/balancer.rb
|
64
88
|
- lib/multidb/configuration.rb
|
65
89
|
- lib/multidb/model_extensions.rb
|
66
90
|
- lib/multidb/version.rb
|
91
|
+
- spec/balancer_spec.rb
|
92
|
+
- spec/helpers.rb
|
93
|
+
- spec/spec_helper.rb
|
67
94
|
homepage: ''
|
68
95
|
licenses: []
|
96
|
+
metadata: {}
|
69
97
|
post_install_message:
|
70
98
|
rdoc_options: []
|
71
99
|
require_paths:
|
72
100
|
- lib
|
73
101
|
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
102
|
requirements:
|
76
|
-
- -
|
103
|
+
- - '>='
|
77
104
|
- !ruby/object:Gem::Version
|
78
105
|
version: '0'
|
79
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
-
none: false
|
81
107
|
requirements:
|
82
|
-
- -
|
108
|
+
- - '>='
|
83
109
|
- !ruby/object:Gem::Version
|
84
110
|
version: '0'
|
85
111
|
requirements: []
|
86
112
|
rubyforge_project: ar-multidb
|
87
|
-
rubygems_version:
|
113
|
+
rubygems_version: 2.0.3
|
88
114
|
signing_key:
|
89
|
-
specification_version:
|
115
|
+
specification_version: 4
|
90
116
|
summary: Multidb is an ActiveRecord extension for switching between multiple database
|
91
117
|
connections, such as master/slave setups.
|
92
|
-
test_files:
|
118
|
+
test_files:
|
119
|
+
- spec/balancer_spec.rb
|
120
|
+
- spec/helpers.rb
|
121
|
+
- spec/spec_helper.rb
|
93
122
|
has_rdoc:
|
data/init.rb
DELETED